# Program 03c: Finding critical points.
# See Example 9.
import sympy as sm

x, y = sm.symbols('x, y')
P = x * (1- x / 2 - y)
Q = y * (x - 1 - y / 2)

# Set P(x,y)=0 and Q(x,y)=0.
Peqn = sm.Eq(P, 0)
Qeqn = sm.Eq(Q, 0)

# Locate critical points
criticalpoints = sm.solve((Peqn, Qeqn), x, y)

print(criticalpoints)


# Refer: https://en.wikipedia.org/wiki/Test_functions_for_optimization

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

pso_solver.setSeed(1)

lower = xlower = ylower = -5
upper = xupper = yupper = 5
particleList = pso_solver.createRandomParticleList(2, numParticles=10, lower=lower, upper=upper)

# Testing on Rastrigin function with n = 2
f = lambda x, y: 20 + (x**2 - 10*np.cos(2*np.pi*x)) + (y**2 - 10*np.cos(2*np.pi*y))

pso_solver.psoVisualizeBivariate(particleList, f, xlower, xupper, ylower, yupper, c1=1, c2=1, W=0.5, numIters=50, maxFlag=False, sleepTime=0.1, density=100, accuracy=2, verbose=False)


# mean = the average value
# median = the mid point value
# mode = the most common value
import numpy as np

speed = np.array( [99,86,87,88,111,86,103,87,94,78,77,85,86] )

mean_value = np.mean(speed)

print('Mean: ', mean_value)

# median value is the value in the middle, after you have sorted all the values

median_value = np.median(speed)

print('Median: ', median_value)

"""
Use the Scipy mode() method to find the number that appears that he most
"""
from scipy import stats

mode_value = stats.mode(speed)

print('Mode: ', mode_value)


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

def re_lu(x):
    return np.maximum(0, x)

def softmax(x):
    exp_x_shifted = np.exp(x - np.max(x))
    exp_sums = np.sum(exp_x_shifted, axis=1).reshape((-1, 1))
    probs = exp_x_shifted / exp_sums
    return probs

def fcann2_train(X, Y_, shape=(-1, 3), max_iter=100_000, eta=0.05, lamda=0.001, print_frequency=100):
    N = len(X)
    n = len(X[0])
    C = np.max(Y_) + 1
    hidden = shape[1]

    W1 = np.random.randn(n, hidden)
    b1 = np.zeros((1, hidden))
    W2 = np.random.randn(hidden, C)
    b2 = np.zeros((1, C))

    Y_one_hot = data.class_to_onehot(Y_)

    for i in range(max_iter):
        # FORWARD
        # 1st layer
        s1 = X @ W1 + b1
        h1 = re_lu(s1)
        # second layer
        s2 = h1 @ W2 + b2
        h2 = re_lu(s2)
        # loss
        P = softmax(h2)

        if i % print_frequency == 0:
            loss = -1.0 / N * np.sum(np.log(P) * Y_one_hot)
            print(f"iteration {i} loss = {loss}")

        # BACKWARD
        dL_ds2 = P - Y_one_hot
        dL_dW2 = h1.T @ dL_ds2
        dL_db2 = np.sum(dL_ds2, axis=0)

        dL_ds1 = dL_ds2 @ W2.T
        dL_ds1[s1 <= 0] = 0
        dL_dW1 = dL_ds1.T @ X
        dL_db1 = np.sum(dL_ds1, axis=0)
        # ADJUSTING WEIGHTS AND BIASES
        W1 = W1 * (1 - eta * lamda) - 1 / N * eta * dL_dW1.T
        b1 -= 1 / N * eta * dL_db1
        W2 = W2 * (1 - eta * lamda) - 1 / N * eta * dL_dW2
        b2 -= 1 / N * eta * dL_db2

    return W1, b1, W2, b2

def fcann2_classify(X, W1, b1, W2, b2):
    s1 = X @ W1 + b1
    h1 = re_lu(s1)
    s2 = h1 @ W2 + b2
    return softmax(s2)

def decfun(W1, b1, W2, b2):
    return lambda X: fcann2_classify(X, W1, b1, W2, b2)[:, 1]

if __name__ == "__main__":
    np.random.seed(100)
    X, Y_ = data.sample_gmm_2d(6, 2, 10)
    W1, b1, W2, b2 = fcann2_train(X, Y_, (-1, 5), 10_000, 0.05, 0.001, 500)
    probs = fcann2_classify(X, W1, b1, W2, b2)
    Y = np.argmax(probs, axis=1)
    bounding_box = (np.min(X, axis=0), np.max(X, axis=0))
    data.graph_surface(decfun(W1, b1, W2, b2), bounding_box, offset=0.5)
    data.graph_data(X, Y_, Y)
    plt.show()


import numpy as np
from random import shuffle

def softmax_loss_naive(W, X, y, reg):
  """
  Softmax loss function, naive implementation (with loops)

  Inputs have dimension D, there are C classes, and we operate on minibatches
  of N examples.

  Inputs:
  - W: A numpy array of shape (D, C) containing weights.
  - X: A numpy array of shape (N, D) containing a minibatch of data.
  - y: A numpy array of shape (N,) containing training labels; y[i] = c means
    that X[i] has label c, where 0 <= c < C.
  - reg: (float) regularization strength

  Returns a tuple of:
  - loss as single float
  - gradient with respect to weights W; an array of same shape as W
  """
  # Initialize the loss and gradient to zero.
  loss = 0.0
  dW = np.zeros_like(W)

  #############################################################################
  # TODO: Compute the softmax loss and its gradient using explicit loops.     #
  # Store the loss in loss and the gradient in dW. If you are not careful     #
  # here, it is easy to run into numeric instability. Don't forget the        #
  # regularization!                                                           #
  #############################################################################
  num_train = X.shape[0]
  num_class = W.shape[1]

  for i in xrange(num_train):
    scores = X[i].dot(W)
    ei = 0
    for j in xrange(num_class):
        ei += np.exp(scores[j])

    for k in xrange(num_class):
        if k == y[i]:
            dW[:,k] += X[i]*(np.exp(scores[k])/ei - 1)
        else:
            dW[:,k] += X[i]*(np.exp(scores[k])/ei)

    loss -= np.log(np.exp(scores[y[i]])/ei)
  loss /= num_train
  loss += 0.5 * reg * np.sum(W**2)

  dW /= num_train
  dW += reg * W

  #############################################################################
  #                          END OF YOUR CODE                                 #
  #############################################################################

  return loss, dW

def softmax_loss_vectorized(W, X, y, reg):
  """
  Softmax loss function, vectorized version.

  Inputs and outputs are the same as softmax_loss_naive.
  """
  # Initialize the loss and gradient to zero.
  loss = 0.0
  dW = np.zeros_like(W)

  #############################################################################
  # TODO: Compute the softmax loss and its gradient using no explicit loops.  #
  # Store the loss in loss and the gradient in dW. If you are not careful     #
  # here, it is easy to run into numeric instability. Don't forget the        #
  # regularization!                                                           #
  #############################################################################
  num_train = X.shape[0]

  #for i in xrange(num_train):
  scores = X.dot(W)
  scores -= np.max(scores)
  ei = np.sum(np.exp(scores), axis=1)
  loss = np.sum(-np.log(np.exp(scores[range(num_train),y])/ei))

  loss /= num_train
  loss += 0.5 * reg * np.sum(W**2)

  e_mat = np.exp(scores)/ei.reshape(-1,1)
  #e_mat = np.exp(scores)/np.matrix(ei).T
  e_mat[range(num_train),y] -= 1
  dW += np.dot(X.T, e_mat)

  dW /= num_train
  dW += reg * W

  #############################################################################
  #                          END OF YOUR CODE                                 #
  #############################################################################

  return loss, dW


import numpy as np

def multinomial_estimation(data, alpha_prior=None):
    """
    Parameter estimation for a multinomial model using count data. Maximumum likelihood (ML) estimation is done if
    `alpha_prior` is not specified; else a maximum-a-posteriori (MAP) estimation is done using a Dirichlet prior
    with the hyper-parameters given by `alpha_prior`.

    Setting each value of `alpha_prior` to `0.5` corresponds to the non-informative Jeffrey's prior.
    Setting each value of `alpha_prior` to `1` corresponds to the uniform prior, which also leads to ML estimation.
    In general, values in `alpha_prior` function as a pseudo (prior) count for each category.

    :param data: numpy array with the count data. Shape `(n, m)`, where `n` is the number of samples and `m` is
                 the number of categories. Each value should be an integer and each row should sum to the same
                 value, the number of trials per sample.
    :param alpha_prior: None or a numpy array with the hyper-parameters of a Dirichlet prior distribution.
                        The array should have shape `(data.shape[1], )` with positive values. When `alpha` is None,
                        it is set to the default value of all ones, which leads to a uniform prior and maximum
                        likelihood estimation.
    :return:
        proba: numpy array with the multinomial probability estimates per category. Has shape `(m, )`, with
               values that sum to 1.
    """
    n_samp, n_cat = data.shape
    v = np.sum(data, axis=1)
    if np.any(np.abs(v - v[0]) > 0.):
        raise ValueError("All columns of the input `data` should sum to the same value, the number of trials "
                         "per sample.")

    n_trials = int(v[0])
    if alpha_prior is None:
        # Uniform prior which results in the maximum likelihood estimate
        alpha_prior = np.ones(n_cat)

    den = np.sum(alpha_prior) - n_cat + n_samp * n_trials
    proba = (alpha_prior - 1. + np.sum(data, axis=0)) / max(den, 1.0)

    return proba

def special_dirichlet_prior(n_cat, eps=0.1):
    """
    When all the alpha values are set to 1, the estimate coincides with the maximum likelihood estimate. In this
    case the alpha values sum to `m` (the number of categories).

    What if we knew that a particular category `i` is more likely (important) than the other categories? We can set
    `alpha_i` to a value close to but slightly smaller than 2, and the values of `alpha_j` (j != i) close to but
    slightly larger than 1 such that the sum of alpha values equals `m + 1`.
    One such choice that emphasizes the i-th category is given by:
    ```
    alpha_i = 1 + 1 - ((m - 1) / m) eps
    alpha_j = 1 + eps / m`, for all j != i
    ```
    With this choice, the sum of `alpha` values will be equal to `m + 1` and the i-th category takes a majority
    chunk of the additional 1 sample. This function returns an array of shape `(m, m)`, where the i-th row has the
    alpha values for the case when the i-th category is more likely than the rest.

    :param n_cat: number of categories. int value > 1.
    :param eps: a small value in (0, 1).

    :return: array where each row has the prior values as explained earlier. Has shape `(n_cat, n_cat)`.
    """
    alpha = (1 + eps / n_cat) * np.ones((n_cat, n_cat))
    v = 2. - ((n_cat - 1.) / n_cat) * eps
    np.fill_diagonal(alpha, v)

    return alpha


"""Tests with kernel density estimation."""
import typing as t

import numpy as np

def kernel_gaussian(inst: np.ndarray) -> np.ndarray:
    """Gaussian kernel."""
    if inst.ndim == 1:
        inst = inst.reshape(-1, 1)

    _, dimension = inst.shape

    aux = np.sum(np.square(inst), axis=1)
    return np.exp(-0.5 * aux) * np.power(2.0 * np.pi, -0.5 * dimension)

def infinity_norm(
        inst: t.Union[np.ndarray, float]) -> t.Union[np.ndarray, float]:
    """Calculates the infinity norm of ``inst``.

    The infinity norm is defined as norm_{inf}(inst) = max_{i}(|x_{i}|), i.e.,
    the maximum absolute value in the vector ``inst``.

    For instance, if inst = [0, 4, -7, 2, -1], then norm_{inf}(inst) = 7.
    """
    return np.max(np.abs(inst), axis=1)

def kernel_uniform(inst: np.ndarray) -> np.ndarray:
    """Uniform kernel."""
    if inst.ndim == 1:
        inst = inst.reshape(-1, 1)

    _, dimension = inst.shape

    return 0.5**dimension * (infinity_norm(inst) < 1.0)

def kernel_epanechnikov(inst: np.ndarray) -> np.ndarray:
    """Epanechnikov kernel."""
    if inst.ndim != 1:
        raise ValueError("'inst' vector must be one-dimensional!")

    return 0.75 * (1.0 - np.square(inst)) * (np.abs(inst) < 1.0)

def kernel_density_est(unknown_points: np.ndarray,
                       kernel: t.Callable[[np.ndarray], np.ndarray],
                       known_points: np.ndarray,
                       kernel_bandwidth: t.Union[int, float, np.number], *args,
                       **kwargs) -> np.ndarray:
    """Calculate the density estimation for ``unknown points`` using ``kernel``.

    Arguments
    ---------
    unknown_points : :obj:`np.ndarray`
        Numpy array with coordinates to evaluate the density function value.

    kernel : :obj:`Callable`
        Callable which implements the kernel function. Must receive a
        numpy array as the first argument, and outputs a another numpy
        array. Can receive additional arguments via *args and **kwargs.

    known_points : :obj:`np.ndarray`
        Set of points given, which partly represents the underlying unknown
        distribution. Used to estimate the density function.

    kernel_bandwidth: :obj:`np.ndarray`
        Length of the ``bumps`` of the kernel function around each
        known point. This parameter must be optimized in order to the
        output density function really fits the ``known_points``
        distribution.

    *args:
        Additional arguments to the ``kernel`` function.

    **kwargs:
        Additional arguments to the ``kernel`` function.

    Returns
    -------
    :obj:`np.ndarray`
        Array containing each ``unknown_points`` evaluated with the kernel
        density estimation technique.
    """
    if isinstance(unknown_points, (float, int, np.number)):
        unknown_points = np.array([unknown_points])

    if known_points.ndim == 1:
        num_inst, dimension = known_points.size, 1

    else:
        num_inst, dimension = known_points.shape

    return np.array([
        np.sum(
            kernel((inst - known_points) / kernel_bandwidth, *args, **kwargs))
        for inst in unknown_points
    ]) / (num_inst * kernel_bandwidth**dimension)

def _experiment_01() -> None:
    """Kernel Density estimation experiment 01."""
    import matplotlib.pyplot as plt

    linear_vals = np.linspace(-3, 3, 100)
    plt.plot(linear_vals, kernel_gaussian(linear_vals), label="Gaussian")
    plt.plot(linear_vals, kernel_uniform(linear_vals), label="Uniform")
    plt.plot(
        linear_vals, kernel_epanechnikov(linear_vals), label="Epanechnikov")
    plt.title("Kernels")
    plt.legend()
    plt.show()

def _experiment_02() -> None:
    """Kernel Density estimation experiment 02."""
    import matplotlib.pyplot as plt

    linear_vals = np.linspace(-3, 3, 100)
    dim_1, dim_2 = np.meshgrid(linear_vals, linear_vals)

    z_gauss = np.zeros((linear_vals.size, linear_vals.size))
    z_uniform = np.zeros((linear_vals.size, linear_vals.size))

    for ind in np.arange(linear_vals.size):
        aux_1 = dim_1[:, ind].reshape(-1, 1)
        aux_2 = dim_2[:, ind].reshape(-1, 1)
        vals = np.hstack((aux_1, aux_2))
        z_gauss[:, ind] = kernel_gaussian(vals)
        z_uniform[:, ind] = kernel_uniform(vals)

    plt.title("Kernels")
    plt.subplot(121)
    plt.contour(dim_1, dim_2, z_gauss)
    plt.subplot(122)
    plt.contour(dim_1, dim_2, z_uniform)
    plt.show()

def _experiment_03() -> None:
    """Estimate Kernel bandwidth."""
    import matplotlib.pyplot as plt
    from cross_validation import loo_cv

    def loss_function(inst):
        """Mean of log-probabilities (0 <= inst <= 1)."""
        return -np.mean(np.log(inst))

    random_state = 16
    chosen_kernel = kernel_gaussian

    np.random.seed(random_state)

    candidate_bandwidths = np.linspace(0.01, 1.0, 25)
    known_points = np.random.normal(size=512)

    logls = np.zeros(candidate_bandwidths.size)

    for subset_test, subset_train in loo_cv(known_points):
        for ind_bandwidth in np.arange(candidate_bandwidths.size):
            kernel_est = kernel_density_est(
                unknown_points=subset_test,
                known_points=subset_train,
                kernel=chosen_kernel,
                kernel_bandwidth=candidate_bandwidths[ind_bandwidth])

            logls[ind_bandwidth] += loss_function(kernel_est)

    bandwidth_opt = candidate_bandwidths[logls.argmin()]

    random_ind = np.random.randint(candidate_bandwidths.size)
    bandwidth_random = candidate_bandwidths[random_ind]

    print("Optimal bandwidth: {} (loss: {})".format(bandwidth_opt,
                                                    logls.min()))
    print("Random bandwidth: {} (loss: {})".format(bandwidth_random,
                                                   logls[random_ind]))

    linear_vals = np.linspace(-3, 3, 100)

    plt.hist(known_points, 32, density=True)
    plt.plot(
        linear_vals,
        kernel_density_est(
            unknown_points=linear_vals,
            known_points=known_points,
            kernel=chosen_kernel,
            kernel_bandwidth=bandwidth_opt))
    plt.plot(
        linear_vals,
        kernel_density_est(
            unknown_points=linear_vals,
            known_points=known_points,
            kernel=chosen_kernel,
            kernel_bandwidth=bandwidth_random))
    plt.show()

if __name__ == "__main__":
    _experiment_01()
    _experiment_02()
    _experiment_03()


"""
Created on Wed Aug 28 12:13:14 2019
@author: Emerson Boeira
"""
#%% Header: importing python packages and libraries

import numpy as np  # important package for scientific computing

#%% Functions that calculate the sample-based and the theoretical autocorrelation of ARMA processes

def smpl_acorr(y, maxlag):
    # Description to help the user
    """Function that calculates the sample-based autocorrelation of the signal y(t), using the numpy.cov() function.
    The advantage os this function is that it's faster and more efficient that numpy.correlate().

    Parameters
    ----------
    y : numpy.ndarray
        Observed signal.
    maxlag: int
        Maximum value of lag that will be considered on the autocorrelation function.

    Returns
    -------
    ryy: numpy.ndarray
        The autocorrelation function, calculated based on the observation of y(t).
    tau: numpy.ndarray
        The lag interval considered. It has the same size as ryy."""

    # calculating the size of tau
    N = 2 * maxlag + 1
    # assembling tau with linspace
    tau = np.linspace(- maxlag, maxlag, N)  # linspace(start, stop, numberofpoints)

    # preallocating the autocorrelation function vector
    ryy = np.zeros((maxlag + 1))

    # calculating the autocorrelation for tau=0 using the cov function
    ryy[0] = np.cov(y[1:], y[:-1])[0][0]

    # calculating the correlation function
    for l in range(1, maxlag + 1):
        ryy[l] = np.cov(y[l:], y[:-l])[0][1]

    # using the flip operation to return a vector that represents the autocorrelation from -maxlag to +maxlag
    ryyf = np.flip(ryy[1:])
    ryyc = np.concatenate((ryyf, ryy))

    # returns the sample-based autocorrelation and the lag vector
    return ryyc, tau

def arma_acorr(C, A, var, maxlag):
    # Description to help the user
    """Function that calculates the theoretical autocorrelation function of an ARMA process:
        A(q)y(t)=C(q)e(t), where
        A(q) and C(q) are defined as polinomials on q (instead of q^{-1})
        e(t) is a white noise sequence with variance: E[e(t)e(t)] = var.

    Parameters
    ----------
    A: numpy.ndarray
        Vector that contains the coefficients of A(q).
    C: numpy.ndarray
        Vector that contains the coefficients of C(q).
    var: float
        Variance of e(t).
    maxlag: int
        Maximum lag that will be considered on the computation of the autocorrelation (from -maxlag to +maxlag).

    Returns
    -------
    ryy: numpy.ndarray
        The autocorrelation function, calculated based on Soderstrom's algorithm.
    tau: numpy.ndarray
        The lag interval considered. It has the same size as ryy."""

    # order of A(q)
    n = A.shape[0] - 1
    # order of C(q)
    m = C.shape[0] - 1

    # calculating C(q^-1)
    cm = np.flip(C)

    # making C(q) and C(q^-1) with the same base
    zc = np.zeros((m))
    C = np.concatenate((C, zc))
    cm = np.concatenate((zc, cm))

    # calculating B(q)
    B = np.convolve(C, cm)
    # fixing the dimensions after the convolve
    B = B[m : 3 * m + 1]
    # making B(q) with the same shape as A(q)
    zb = np.zeros((n - m))
    B = np.concatenate((zb, B))
    B = np.concatenate((B, zb))
    # taking only the redundant part of B(q)
    Bn = B[0 : n + 1]
    # fliping the bn vector to find D(q)
    Bn = np.flip(Bn)

    # preallocating the A1 and A2 matrices
    A1 = np.zeros((n + 1, n + 1))
    A2 = np.zeros((n + 1, n + 1))

    # assembling A1 and A2
    for k in range(0, n + 1):
        A1[k][0 : n + 1 - k] = A[k : n + 1]
        A2[k][k : n + 1] = A[0 : n + 1 - k]

    # assembling the matrix "calligraphic A" - to avoid redundance we'll call it Acal
    Acal = A1 + A2

    # finding the polynomial D(q)
    D = np.linalg.solve(Acal, Bn)

    # using the function coeff to calculate the coefficients of the correlation based on A(q) and D(q)
    ryy, tau = coeff(A, D, maxlag)

    # scaling the correlation function with the variance of e(t)
    ryy = var * ryy

    # returning the theoretical correlation and the lag vector
    return ryy, tau

def coeff(A, D, maxlag):
     # Description to help the user
    """Function that calculates the coefficients of the theoretical correlation, based on the A(q) and D(q) polynomials,
    from -maxlag to +maxlag.

    Parameters
    ----------
    A: numpy.ndarray
        Vector that contains the coefficients of A(q).
    D: numpy.ndarray
        Vector that contains the coefficients of D(q).
    maxlag: int
        Maximum lag that will be considered on the computation of the autocorrelation (from -maxlag to +maxlag).

    Returns
    -------
    ryy: numpy.ndarray
        The autocorrelation function, calculated based on Soderstrom's algorithm.
    tau: numpy.ndarray
        The lag interval considered. It has the same size as ryy."""

    # preallocating the correlation function vector
    ryy = np.zeros((maxlag + 1))

    # computing the order of A(q)
    n = A.shape[0] - 1

    # calculating the first coefficient of the correlation function
    ryy[0] = 2 * D[0]
    # calculating the second coefficient of the correlation function
    ryy[1] = D[1] - A[1]*D[0]

    # loop that calculates the other coefficients
    for k in range(2, maxlag + 1):
        Sum = 0
        if k <= n:
            for j in range(1, k):
                Sum = Sum + A[j]*ryy[k - j]
            ryy[k] = D[k]-A[k]*D[0]-Sum
        else:
            for j in range(1, n + 1):
                Sum = Sum + A[j]*ryy[k - j]
            ryy[k] = -Sum

    # using the flip operation to return a vector that represents the autocorrelation from -maxlag to +maxlag
    ryyf=np.flip(ryy[1:])
    ryyc = np.concatenate((ryyf, ryy))

    # calculating the size of tau
    N = 2 * maxlag + 1
    # assembling tau with linspace
    tau = np.linspace(- maxlag, maxlag, N)  # linspace(start, stop, numberofpoints)

    # returning
    return ryyc, tau


#https://youtu.be/tnaq2Ao4KBE#Ref: Sreenivas Sarwar Anik
"""
A quick overview of timeseries.

Dataset from: https://www.kaggle.com/rakannimer/air-passengers
International Airline Passengers prediction problem.
This is a problem where, given a year and a month, the task is to predict
the number of international airline passengers in units of 1,000.
The data ranges from January 1949 to December 1960, or 12 years, with 144 observations.
"""

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
plt.style.use('dark_background')

# load the dataset
df = pd.read_csv('data/AirPassengers.csv')
print(df.dtypes)

df['Month'] = pd.to_datetime(df['Month'])
print(df.dtypes)

df.set_index('Month', inplace=True)

plt.plot(df['Passengers'])

#Is the data stationary?
#Dickey-Fuller test
from statsmodels.tsa.stattools import adfuller
adf, pvalue, usedlag_, nobs_, critical_values_, icbest_ = adfuller(df)
print("pvalue = ", pvalue, " if above 0.05, data is not stationary")
#Since data is not stationary, we may need SARIMA and not just ARIMA

#
df['year'] = [d.year for d in df.index]
df['month'] = [d.strftime('%b') for d in df.index]
years = df['year'].unique()

#Plot yearly and monthly values as boxplot
sns.boxplot(x='year', y='Passengers', data=df)
sns.boxplot(x='month', y='Passengers', data=df)

#Extract and plot trend, seasonal and residuals.
from statsmodels.tsa.seasonal import seasonal_decompose
decomposed = seasonal_decompose(df['Passengers'],
                            model ='additive')

#Additive time series:
#Value = Base Level + Trend + Seasonality + Error
#Multiplicative Time Series:
#Value = Base Level x Trend x Seasonality x Error

trend = decomposed.trend
seasonal = decomposed.seasonal #Cyclic behavior may not be seasonal!
residual = decomposed.resid

plt.figure(figsize=(12,8))
plt.subplot(411)
plt.plot(df['Passengers'], label='Original', color='yellow')
plt.legend(loc='upper left')
plt.subplot(412)
plt.plot(trend, label='Trend', color='yellow')
plt.legend(loc='upper left')
plt.subplot(413)
plt.plot(seasonal, label='Seasonal', color='yellow')
plt.legend(loc='upper left')
plt.subplot(414)
plt.plot(residual, label='Residual', color='yellow')
plt.legend(loc='upper left')
plt.show()

#AUTOCORRELATION
#Autocorrelation is simply the correlation of a series with its own lags.
# Plot lag on x axis and correlation on y axis
#Any correlation above confidence lnes are statistically significant.

from statsmodels.tsa.stattools import acf

acf_144 = acf(df.Passengers, nlags=144)
plt.plot(acf_144)

#Obtain the same but with single line and more info...
from pandas.plotting import autocorrelation_plot
autocorrelation_plot(df.Passengers)
#Horizontal bands indicate 95% and 99% (dashed) confidence bands

#A strong positive correlation for lags below 40 (months)


#! /usr/bin/env python

"""
File: interpolate_exp_cos.py

Copyright (c) 2016 Taylor Patti

License: MIT

This module calculates an interpolant approximation to the given function at the given point.

"""

import numpy as np

def exp_cos_func(q):
    """Approximates interpolant approximation to the function."""
    mesh = np.linspace(-1, 1, q+1)
    f = np.exp(- mesh**2)*np.cos(2 * np.pi * mesh)
    x_point = -0.45
    step = 2 / float(q+1)
    k_val = int(1-x_point / step)
    approximation = f[k_val] + ((f[k_val+1] - f[k_val])/(mesh[k_val+1] - mesh[k_val])) * (x_point - mesh[k_val])
    exact = f = np.exp(- x_point**2)*np.cos(2 * np.pi * x_point)
    return approximation, exact - approximation

def test_approx():
    """Ensures that the approximation is accurate at q = 8"""
    apt = np.fabs(exp_cos_func(8)[1]) < 0.1
    msg = 'Approximation not accurate.'
    assert apt, msg


# coding=utf-8
"""
Daniel Calderon, CC3501, 2019-1
Transformation matrices for computer graphics
v1.0
"""

import numpy as np

def identity():
    return np.identity(4, dtype=np.float32)

def uniformScale(s):
    return np.array([
        [s,0,0,0],
        [0,s,0,0],
        [0,0,s,0],
        [0,0,0,1]], dtype = np.float32).T

def scale(sx, sy, sz):
    return np.array([
        [sx,0,0,0],
        [0,sy,0,0],
        [0,0,sz,0],
        [0,0,0,1]], dtype = np.float32).T

def rotationX(theta):
    sin_theta = np.sin(theta)
    cos_theta = np.cos(theta)

    return np.array([
        [1,0,0,0],
        [0,cos_theta,-sin_theta,0],
        [0,sin_theta,cos_theta,0],
        [0,0,0,1]], dtype = np.float32).T

def rotationY(theta):
    sin_theta = np.sin(theta)
    cos_theta = np.cos(theta)

    return np.array([
        [cos_theta,0,sin_theta,0],
        [0,1,0,0],
        [-sin_theta,0,cos_theta,0],
        [0,0,0,1]], dtype = np.float32).T

def rotationZ(theta):
    sin_theta = np.sin(theta)
    cos_theta = np.cos(theta)

    return np.array([
        [cos_theta,-sin_theta,0,0],
        [sin_theta,cos_theta,0,0],
        [0,0,1,0],
        [0,0,0,1]], dtype = np.float32).T

def rotationA(theta, axis):
    s = np.sin(theta)
    c = np.cos(theta)

    assert axis.shape == (3,)

    x = axis[0]
    y = axis[1]
    z = axis[2]

    return np.array([
        # First row
        [c + (1 - c) * x * x,
        (1 - c) * x * y - s * z,
        (1 - c) * x * z + s * y,
        0],
        # Second row
        [(1 - c) * x * y + s * z,
        c + (1 - c) * y * y,
        (1 - c) * y * z - s * x,
        0],
        # Third row
        [(1 - c) * x * z - s * y,
        (1 - c) * y * z + s * x,
        c + (1 - c) * z * z,
        0],
        # Fourth row
        [0,0,0,1]], dtype = np.float32).T

def translate(tx, ty, tz):
    return np.array([
        [1,0,0,tx],
        [0,1,0,ty],
        [0,0,1,tz],
        [0,0,0,1]], dtype = np.float32).T

def shearing(xy, yx, xz, zx, yz, zy):
    return np.array([
        [ 1, xy, xz, 0],
        [yx,  1, yz, 0],
        [zx, zy,  1, 0],
        [ 0,  0,  0, 1]], dtype = np.float32).T

def matmul(mats):
    out = mats[-1]
    for i in range(len(mats) - 2, -1, -1):
        out = np.matmul(mats[i], out)

    return out


from sage.all import ZZ

def attack(N, e, c, oracle):
    """
    Recovers the plaintext from the ciphertext using the LSB oracle attack.
    :param N: the modulus
    :param e: the public exponent
    :param c: the encrypted message
    :param oracle: a function which returns the last bit of a plaintext for a given ciphertext
    :return: the plaintext
    """
    left = ZZ(0)
    right = ZZ(N)
    while right - left > 1:
        c = (c * pow(2, e, N)) % N
        if oracle(c) == 0:
            right = (right + left) / 2
        else:
            left = (right + left) / 2

    return int(right)


import math
import numpy as np

def allPossibilities(N):
    if N == 1: return ["H","T"]
    List1 = ["H","T"]
    for x in range(N-1):
        List2 = []
        for x in List1:
                   List2.append(x+"H")
                   List2.append(x+"T")
        List1 = List2.copy()
    return List2

def probabilityXcoinsYheads(x,y,headChance=0.5):
    a = int(math.factorial(x)/math.factorial(y)/math.factorial(x-y))
    b = 2**x
    c = a / b
    d = a*headChance**(y)*(1-headChance)**(x-y)
    return a,b,c,d

# sequence type should be str
def probability(sequence,coinPickChance,headChance):
    p = []
    for x in range(len(coinPickChance)):
        p.append(coinPickChance[x])
        for y in sequence:
            if y == "H": p[x]*=headChance[x]
            else: p[x]*=(1-headChance[x])
    return sum(p)

def simulatingFlippingCoins(success=[1], size=1, coins=[1,0], probability=[0.5,0.5], tests=1000000):
    return sum([((np.random.choice(coins,size=(tests,size),p=probability)).sum(axis=1)==i).mean() for i in success])


import numpy as np
import matplotlib.pyplot as plt

def mandelbrot(height, width, x=-0.5, y=0, zoom=1, max_iterations=100):
    # To make navigation easier we calculate these values
    x_width = 1.5
    y_height = 1.5*height/width
    x_from = x - x_width/zoom
    x_to = x + x_width/zoom
    y_from = y - y_height/zoom
    y_to = y + y_height/zoom

    # Here the actual algorithm starts
    x = np.linspace(x_from, x_to, width).reshape((1, width))
    y = np.linspace(y_from, y_to, height).reshape((height, 1))
    c = x + 1j * y

    # Initialize z to all zero
    z = np.zeros(c.shape, dtype=np.complex128)
    # To keep track in which iteration the point diverged
    div_time = np.zeros(z.shape, dtype=int)
    # To keep track on which points did not converge so far
    m = np.full(c.shape, True, dtype=bool)

    for i in range(max_iterations):
        z[m] = z[m]**2 + c[m]

        diverged = np.greater(np.abs(z), 2, out=np.full(c.shape, False), where=m) # Find diverging

        div_time[diverged] = i      # set the value of the diverged iteration number
        m[np.abs(z) > 2] = False    # to remember which have diverged
    return div_time

# Default image of Mandelbrot set
plt.imshow(mandelbrot(800, 1000), cmap='magma')
# The image below of Mandelbrot set
# plt.imshow(mandelbrot(800, 1000, -0.75, 0.0, 2, 200), cmap='magma')
# The image below of below of Mandelbrot set
# plt.imshow(mandelbrot(800, 1000, -1, 0.3, 20, 500), cmap='magma')
plt.show()


from numpy import cross, array , vdot
from numpy.linalg import norm
import matplotlib.pyplot as plt
from roblib import *
def vct_nrm(a,b,c):
	"""Soit a,b,c trois coin de la plateforme supossée carrée, n est un vecteur normal de cette platforme"""
	V1 = a-b
	V2 = a-c
	n = cross(V1,V2).T
	return n/norm(n)

def champ(p,n,phat,v_d):
	"""p position du drone, n vecteur normal à la plateforme, phat point cible où attérir, v_d vecteur vitesse de la plateforme"""
	calc1 = cross(n.T,(p-phat).T)
	pt_attract = 1*(phat-p)
	vitesse_cible = 0.5*v_d
	Q = 0.4*cross(n.T,calc1)+pt_attract.T + vitesse_cible

	return Q

def draw_shampoing(p):
	#ax.scatter(p[0],p[1],p[2]) #p
	Q = champ(p,n,phat)
	Q = Q.flatten()
	p = p.flatten()
	ax.plot([p[0],p[0]+Q[0]],[p[1],p[1]+Q[1]],[p[2],p[2]+Q[2]],'g-') #champ au point p

a = array([[0,5,0]])
b = array([[1,0,0]])
c = array([[0,1,0]])

n = vct_nrm(a,b,c)
print("vecteur normal = ",n)
phat = array([[100],[0],[0]]) #position point d'attérissage
p = array([[0],[0],[100]]) #position drone
Q = champ(p,n,phat)
print("n.Q",vdot(n, Q))
print("valeur du champ au point",Q)

a = a.flatten()
b = b.flatten()
c = c.flatten()

fig   = figure()
ax    = Axes3D(fig)
# for x in arange(0,1,0.1):
# 	for y in arange(0,1,0.1):
# 		for z in arange(0,3,0.25):
# 			draw_shampoing(array([[x,y,z]]).T)

# phat = phat.flatten()
# ax.scatter(phat[0],phat[1],phat[2]) #phat
# n = n.flatten()
# ax.plot([phat[0],phat[0]+3*n[0]],[phat[1],phat[1]+3*n[1]],[phat[2],phat[2]+3*n[2]]) #vecteur normal à partir de phat
# ax.plot([a[0],b[0],c[0],a[0]],[a[1],b[1],c[1],a[1]],[a[2],b[2],c[2],a[2]]) #platforme
# pause(10)
"""
plt.figure()
plt.xlim((-3,3))
plt.ylim((-3,3))
plt.plot(phat[0,0],phat[1,0],'ob')
plt.plot(p[0,0],p[1,0],'or')
plt.plot([p.flatten()[0],p.flatten()[0]+Q.flatten()[0]],[p.flatten()[1],p.flatten()[1]+Q.flatten()[1]])
plt.show()"""


import pandas as pd
import numpy as np
import matplotlib
matplotlib.use('TkAgg')
from matplotlib import pyplot as plt
import seaborn as seabornInstance
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn import metrics
import os

folder = os.path.abspath(os.path.join(os.path.dirname( __file__ ), '..', 'data'))

dataset = pd.read_csv(folder+'/Weather.csv')
#Explore the data
print("dataset.shape:", dataset.shape)
print("Statistical characteristics in the data:", dataset.describe())

dataset.plot(x='MinTemp', y='MaxTemp', style='o')
plt.title('MinTemp vs MaxTemp')
plt.xlabel('MinTemp')
plt.ylabel('MaxTemp')
plt.show()

plt.figure(figsize=(15,10))
plt.tight_layout()
seabornInstance.distplot(dataset['MaxTemp'])
plt.show()

#Our next step is to divide the data into “attributes” and “labels”.
#Attributes are the independent variables while labels are dependent variables whose
# values are to be predicted. In our dataset, we only have two columns. We want to
# predict the MaxTemp depending upon the MinTemp recorded.
# Therefore our attribute set will consist of the “MinTemp” column which is stored in
# the X variable, and the label will be the “MaxTemp” column which is stored in y variable.
kk=X = dataset['MinTemp'].values
X = dataset['MinTemp'].values.reshape(-1,1)
y = dataset['MaxTemp'].values.reshape(-1,1)

#Next, we split 80% of the data to the training set while 20% of the data to test set
# using below code.
#The test_size variable is where we actually specify the proportion of the test set.
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=0)

#As we have discussed that the linear regression model basically finds the best value
# for the intercept and slope, which results in a line that best fits the data.
# To see the value of the intercept and slope calculated by the linear regression
# algorithm for our dataset, execute the following code.

regressor = LinearRegression()
regressor.fit(X_train, y_train) #training the algorithm

#To retrieve the intercept:
print(regressor.intercept_)
#For retrieving the slope:
print(regressor.coef_)
#To make predictions on the test data, execute the following script:
y_pred = regressor.predict(X_test)

df = pd.DataFrame({'Actual': y_test.flatten(), 'Predicted': y_pred.flatten()})
df
plt.figure()
plt.scatter(X_test, y_test,  color='gray')
plt.plot(X_test, y_pred, color='red', linewidth=2)
plt.show()

#Error metrics of the estimation
print('Mean Absolute Error:', metrics.mean_absolute_error(y_test, y_pred))
print('Mean Squared Error:', metrics.mean_squared_error(y_test, y_pred))
print('Root Mean Squared Error:', np.sqrt(metrics.mean_squared_error(y_test, y_pred)))


import numpy as np

# ============================================================
# principal rotations

# rotation of phi is about the 1st axis (=X-axis) of the inertial frame
def r1(phi):
    return np.array([[1, 0, 0],
                     [0, np.cos(phi), np.sin(phi)],
                     [0, -np.sin(phi), np.cos(phi)]])

# second rotation of theta is about the 2nd axis (=Y-axis) of the first intermediate frame
def r2(theta):
    return np.array([[np.cos(theta), 0, -np.sin(theta)],
                     [0, 1, 0],
                     [np.sin(theta), 0, np.cos(theta)]])

# third rotation of psi is about the 3rd axis (=Z-axis) of the second intermediate frame
def r3(psi):
    return np.array([[np.cos(psi), np.sin(psi), 0],
                     [-np.sin(psi), np.cos(psi), 0],
                     [0, 0, 1]])

# ====================================================
# e123 rotation sequence

def q11(psi, theta):
    return np.cos(psi) * np.cos(theta)

def q12(psi, theta, phi):
    return np.cos(psi) * np.sin(theta) * np.sin(phi) + np.sin(psi) * np.cos(phi)

def q13(psi, theta, phi):
    return -np.cos(psi) * np.sin(theta) * np.cos(phi) + np.sin(psi) * np.sin(phi)

def q21(psi, theta):
    return - np.sin(psi) * np.cos(theta)

def q22(psi, theta, phi):
    return -np.sin(psi) * np.sin(theta) * np.sin(phi) + np.cos(psi) * np.cos(phi)

def q23(psi, theta, phi):
    return np.sin(psi) * np.sin(theta) * np.cos(phi) + np.cos(psi) * np.sin(phi)

def q31(theta):
    return np.sin(theta)

def q32(theta, phi):
    return - np.cos(theta) * np.sin(phi)

def q33(theta, phi):
    return np.cos(theta) * np.cos(phi)

def e123_dcm(psi, theta, phi):
    return np.array([[q11(psi, theta), q12(psi, theta, phi), q13(psi, theta, phi)],
                     [q21(psi, theta), q22(psi, theta, phi), q23(psi, theta, phi)],
                     [q31(theta), q32(theta, phi), q33(theta, phi)]])

def getRotationMatrix(vec1, vec2):
    """ Find the rotation matrix that aligns vec1 to vec2
    :param vec1: A 3d "source" vector
    :param vec2: A 3d "destination" vector
    :return mat: A transform matrix (3x3) which when applied to vec1, aligns it with vec2.
    """
    a, b = (vec1 / np.linalg.norm(vec1)).reshape(3), (vec2 / np.linalg.norm(vec2)).reshape(3)
    v = np.cross(a, b)
    c = np.dot(a, b)
    s = np.linalg.norm(v)
    kmat = np.array([[0, -v[2], v[1]], [v[2], 0, -v[0]], [-v[1], v[0], 0]])
    rotation_matrix = np.eye(3) + kmat + kmat.dot(kmat) * ((1 - c) / (s ** 2))
    return rotation_matrix


import numpy as np
import datetime
import math
from scipy import optimize
# (perihelion, period)
orbital_data = {'earth':({2018:(1,3), 2019:(1,3),2020:(1,5)},
                365.25635, 0.016710219,1.496e8)}

# (Axial tilt, rotation (rad/day) per day)
rotation_data = {'earth':(23.44, 6.30046407)}

'''Orbital up vector (orthogonal to earths orbit plane)
Note I am using plane span({(1,0,0), (0,0,1)})
as the plane of reference for all computations.
'''
orbital_up = np.array([0,1,0])

def mean_anomaly(date:"(Year, Month, Day)", body = 'earth'):
    iyear, imonth, iday = date
    perihelion_data, period, eccentricity, semi_major_axis = orbital_data[body]
    perihelion = perihelion_data[iyear]

    day = datetime.date(iyear, imonth, iday)
    perihelion_day = datetime.date(iyear, perihelion[0], perihelion[1])

    #If the date is before the this years perihelion date,
    #use last years perihelion
    if(day < perihelion_day):
        perihelion = perihelion_data[iyear - 1]
        perihelion_day = datetime.date(iyear - 1, perihelion[0], perihelion[1])

    t = (day - perihelion_day).days
    n = 2*(math.pi) / period
    return n * t

def eccentric_anomaly(date:"(Year, Month, Day)", body = 'earth'):
    perihelion_data, period, eccentricity, semi_major_axis = orbital_data[body]
    M = mean_anomaly(date, body)

    keplerf = lambda E: E - eccentricity*math.sin(E) - M
    keplerf_prime = lambda E: 1 -eccentricity*math.cos(E)
    keplerf_prime2 = lambda E: eccentricity*math.sin(E)

    E = optimize.newton(keplerf, 0,
                        fprime = keplerf_prime,
                        fprime2 = keplerf_prime2)
    return E

def true_anomaly(date:"(Year, Month, Day)", body = 'earth'):
    perihelion_data, period, eccentricity, semi_major_axis = orbital_data[body]
    E = eccentric_anomaly(date, body)

    Theta = 2 * math.atan(math.sqrt((1+eccentricity)/(1-eccentricity)) *
            math.tan(E/2))
    return Theta

def heliocentric_distance(date:"(Year, Month, Day)", body = 'earth'):
    perihelion_data, period, eccentricity, semi_major_axis = orbital_data[body]

    E = eccentric_anomaly(date, body)
    Theta = true_anomaly(date,body)
    r = semi_major_axis * (1 - eccentricity*math.cos(E))
    return r

def cartesian_coordinates(date:"(Year, Month, Day)", body = 'earth'):
    Theta = true_anomaly(date,body)
    r = heliocentric_distance(date,body)
    return np.array([r * math.cos(Theta),0,r * math.sin(Theta)])


from math import floor, modf
from numbers import Real
from typing import List

from pandas import DataFrame
from pandas.core.series import Series
from numpy import mean, median

from marco.quantitative_frame import QuantitativeFrame

class UngroupedFrame(QuantitativeFrame):
    """Quantitative ungrouped data entity"""

    def arithmetic_mean(self) -> Real:
        return mean(self.data)

    def median(self) -> Real:
        return median(self.data)

    def trend(self) -> Real:
        _, row = self._find_trend_row()
        return row["Clase"]

    def median_row(self) -> Series:
        middle = self.median()
        index = floor(len(self.dataframe) / 2)
        if len(self.dataframe) % 2 != 0:
            index = next(
                i for i, row in self.dataframe.iterrows() if row["Clase"] == middle
            )
        return self.dataframe.iloc[[index]]

    def trend_row(self) -> DataFrame:
        (index, _) = self._find_trend_row()
        return self.dataframe.iloc[[index]]

    def quantile(self) -> Series:
        return Series(self.data).quantile([.25, .5, .75])

    def _dispersion_bias_of(self, k: int, divisor: int) -> Real:
        n = len(self.data)
        frac, whole = modf((k * (n + 1)) / divisor)
        position = floor(whole)
        if position >= n:
            return self.data[n - 1]
        coeficient = (self.data[position + 1] - self.data[position]) * frac
        return self.data[position] + coeficient

    def decile(self, k: int) -> List[Real]:
        return [self._dispersion_bias_of(element, 10) for element in k]

    def percentile(self, k: List[int]) -> List[Real]:
        return [self._dispersion_bias_of(element, 100) for element in k]


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

def get_integer(msg="Number: ", wrng_msg="Invalid Input"):
    try:
        i = int(input(msg))
    except ValueError:
        print(wrng_msg)
        return get_integer(msg, wrng_msg)
    else:
        return i

def get_float(msg="Number: ", wrng_msg="Invalid Input"):
    try:
        f = float(input(msg))
    except ValueError:
        print(wrng_msg)
        return get_float(msg, wrng_msg)
    else:
        return f

def plot_circle():
    print("""
Please enter the radius of circle and the coordinates of its centres in the form "x y", for eg, '3 0'
""")
    x = []
    y = []

    start = 0
    end = 2 * pi
    i = start

    radius = get_float("Radius: ")
    inp = input("Centre coords, default=0,0: ")
    if inp != "":
        cx, cy = inp.split()
        cx, cy = float(cx), float(cy)
    else:
        cx, cy = 0, 0
    resolution = pi / 180

    while i < end + resolution:
        x.append(cx + radius * cos(i))
        y.append(cy + radius * sin(i))
        i += resolution

    plt.plot(x, y)
    plt.plot(cx, cy, "o")
    # legend
    if cx == 0 and cy == 0:
        legends.append(u"x\u00B2 + y\u00B2 = " + str(radius**2))
    elif cx != 0 and cy == 0:
        if cx > 0:
            legends.append(u"(x - " + str(cx) + ")\u00B2 + y\u00B2 = " + str(radius**2))
        else:
            legends.append(u"(x + " + str(-cx) + ")\u00B2 + y\u00B2 = " + str(radius**2))
    elif cx == 0 and cy != 0:
        if cy > 0:
            legends.append(u"x\u00B2 + (y - " + str(cy) + ")\u00B2 = " + str(radius**2))
        else:
            legends.append(u"x\u00B2 + (y + " + str(-cy) + ")\u00B2 = " + str(radius**2))
    else:
        if cx < 0 and cy < 0:
            legends.append(u"(x + " + str(-cx) + ")\u00B2 + (y + " + str(-cy) + ")\u00B2 = " + str(radius**2))
        elif cx > 0 and cy < 0:
            legends.append(u"(x - " + str(cx) + ")\u00B2 + (y + " + str(-cy) + ")\u00B2 = " + str(radius**2))
        elif cx < 0 and cy > 0:
            legends.append(u"(x + " + str(-cx) + ")\u00B2 + (y - " + str(cy) + ")\u00B2 = " + str(radius**2))
        else:
            legends.append(u"(x - " + str(cx) + ")\u00B2 + (y - " + str(cy) + ")\u00B2 = " + str(radius**2))
    legends.append(f"Circle centre({cx}, {cy})")
    print(f"Circle with centre = ({cx}, {cy}) and radius = {radius} plotted!")

def plot_ellipse():
    print("""
To plot an ellipse please give the values of a and b respectively
""")

    start = 0
    end = 2 * pi
    theta = np.linspace(start, end, 360)

    a = get_float("a: ")
    b = get_float("b: ")

    x = a * np.cos(theta)
    y = b * np.sin(theta)

    plt.plot(x, y)
    legends.append(u"x\u00B2/" + str(a**2) + " + y\u00B2/" + str(b**2) + " = 1")
    print(u"Ellipse: x\u00B2/" + str(a**2) + " + y\u00B2/" + str(b**2) + " = 1 plotted!")
    if a < b:
        c = (b**2 - a**2)**0.5
        plt.plot([0, 0], [c, -c], "o")
        legends.append(f"Ellipse foci(0, ±{round(c, 3)})")
    elif a > b:
        c = (a**2 - b**2)**0.5
        plt.plot([c, -c], [0, 0], "o")
        legends.append(f"Ellipse foci(±{round(c, 3)}, 0)")

def plot_quadrilateral():
    inp = get_integer("""
Choose one way...
1. By providing length and breadth,plot rectangle/square, from the origin.
2. By providing coordinates of all four points.
How would you like to proceed(1 or 2): """, "Invalid input, enter either 1 or 2")
    if inp == 1:
        length = get_float("Length: ")
        breadth = get_float("Breadth: ")
        x = [0, length, length, 0, 0]
        y = [0, 0, breadth, breadth, 0]
        if length != breadth:
            legends.append(f"Rectangle(l={length}, b={breadth})")
            print(f"Rectangle(l={length}, b={breadth}) plotted!")
        else:
            legends.append(f"Square(a={length})")
            print(f"Square(a={length}) plotted")
        plt.plot(x, y, 'o-')
    elif inp == 2:
        x = []
        y = []
        print("Enter points in the form 'x y'")
        for i in range(4):
            a, b = input(f"Point {i+1}: ").split()
            a, b = float(a), float(b)
            x.append(a)
            y.append(b)
        x.append(x[0])
        y.append(y[0])
        legends.append(f"Quadrilateral")
        print('Quadrilateral plotted')
        plt.plot(x, y, "o-")
    else:
        print("Invalid input")

def lnr_cnsts(a):
    consts = []
    x1 = -1
    y1 = -1
    if 'x' in a:
        x1 = a.index('x')
    if x1 >= 1:
        l = a[:x1]
    elif x1 == 0:
        l = 1
    else:
        l = 0
    if l == '+':
        l = 1
    elif l == '-':
        l = -1
    l = float(l)
    consts.append(l)
    if 'y' in a:
        y1 = a.index('y')
    if y1 >= 1:
        m = a[x1 + 1:y1]
    elif y1 == 0:
        m = 1
    else:
        m = 0
    if m == '+':
        m = 1
    elif m == '-':
        m = -1
    m = float(m)
    consts.append(m)
    if y1 != -1:
        if len(a) - 1 != y1:
            n = a[y1 + 1:]
        else:
            n = 0
    else:
        if len(a) - 1 != x1:
            n = a[x1 + 1:]
        else:
            n = 0
    n = float(n)
    consts.append(n)
    return consts

def plot_lnreqn():

    print('''
You can get solution of any two pair of linear equations using this program.
Please enter equations in the form "ax + by + c"''')

    en = input('Equation: ')
    eqn = ''
    e = en.split()
    for i in e:
        eqn += i

    constants = lnr_cnsts(eqn)
    a, b, c = constants[0], constants[1], constants[2]
    if a != 0 and b != 0:
        xval = []
        yval = []
        l = 5
        x = (-c) / a
        y = (-c) / b
        if x >= 0:
            end = x + l
            start = -l
        else:
            end = l
            start = x - l
        resolution = 0.01
        i = start
        while i <= end:
            xval.append(i)
            yval.append(((-c) - (a * i)) / b)
            i += resolution
        plt.plot(xval, yval)
        legends.append(eqn)
        plt.plot([x, 0], [0, y], 'o')
        legends.append(u"Soln. to linear eq\u2099")
        print(f"{eqn} plotted!")
    elif a == 0 and b != 0:
        xval = []
        yval = []
        l = 5
        y = (-c) / b
        start = -l
        end = l
        resolution = l
        i = start
        while i <= end:
            xval.append(i)
            yval.append(y)
            i += resolution
        plt.plot(xval, yval)
        legends.append(eqn)
        plt.plot([0], [y], 'o')
        legends.append(u"Soln. to linear eq\u2099")
        print(f"{eqn} plotted!")
    elif a != 0 and b == 0:
        xval = []
        yval = []
        l = 5
        x = (-c) / a
        start = -l
        end = l
        resolution = l
        i = start
        while i <= end:
            xval.append(x)
            yval.append(i)
            i += resolution
        plt.plot(xval, yval)
        legends.append(eqn)
        plt.plot([x], [0], 'o')
        legends.append(u"Soln. to linear eq\u2099")
        print(f"{eqn} plotted!")

def plot_quadratic():
    print(u"""
A quadratic equation is in the form of ax\u00B2 + bx +c = 0. To plot, please provide a, b, c.
""")
    a = get_float("a: ")
    b = get_float("b: ")
    c = get_float("c: ")

    d = (b**2 - (4 * a * c)) ** 0.5
    x1 = ((-b) + d)/(2 * a)
    x2 = ((-b) - d)/(2 * a)

    print(f"Solution to this equation is x = {x1}, {x2}")
    l = 2
    if x1 <= x2:
        start = x1 - l
        end = x2 + l
    else:
        start = x2 - l
        end = x1 + l

    resolution = 0.01
    x = []
    y = []
    i = start
    while i <= end:
        x.append(i)
        y.append((a * (i ** 2)) + (b * i) + c)
        i += resolution

    plt.plot(x, y)
    legends.append(u""+str(a)+"x\u00B2 + " + str(b) + "x + " + str(c))
    plt.plot([x1, x1], [0, 0], "o")
    legends.append("Quadratic equation solution(s)")
    print(u""+str(a)+"x\u00B2 + " + str(b) + "x + " + str(c) + " plotted!")

def plot_polygon():
    print("""
To plot a polygon, provide its points, minimum of 3 to form a polygon.
To give a point, write its coordinates in the form 'x y', eg '3 2'.
Once you are done giving points, just press 'e' and press enter.
""")
    x = []
    y = []
    pointNo = 1
    poly = {3:"Triangle", 4:"Quadrilateral", 5:"Pentagon", 6:"Hexagon", 7:"Septagon", 8:"Octagon", 9:"Nonagon", 10:"Decagon"}
    while True:
        inp = input(f"Point {pointNo}: ")
        if inp.lower() == "e":
            if pointNo >= 4:
                x.append(x[0])
                y.append(y[0])
                break
            else:
                print("Insufficient points to form a polygon")
                pointNo -= 1
        else:
            xval, yval = inp.split()
            xval, yval = float(xval), float(yval)
            x.append(xval)
            y.append(yval)
        pointNo += 1
    plt.plot(x, y, 'o-')
    legends.append(f"{poly.get(pointNo-1, 'Polygon')}")
    print(f"{poly.get(pointNo-1, 'Polygon')} plotted!")

legends = []

while True:
    action = get_integer("""
1. Plot circle
2. Plot ellipse
3. Plot Quadrilateral
4. Plot linear equation in one/two variables
5. Plot quadratic equation
6. Plot polygon
7. Show plotted graph
8. Exit
Choose a action (1-8): """, "Invalid input, please enter the integer code(1-8)")

    if action == 1:
        plot_circle()
    elif action == 2:
        plot_ellipse()
    elif action == 3:
        plot_quadrilateral()
    elif action == 4:
        plot_lnreqn()
    elif action == 5:
        plot_quadratic()
    elif action == 6:
        plot_polygon()
    elif action == 7:
        plt.grid(True)
        leg = input("Would you like to have legends in graph(y/n)(default y)? ").lower()
        if leg == "" or leg == "y" or leg == "yes":
            plt.legend(legends)
        elif leg == "n" or leg == "no":
            pass
        plt.show()
    elif action == 8:
        break
    else:
        print('Invalid input')


import numpy as np
from math import pi, cos, sin, tan

def pad_ones(x, y, z):
    return np.array([x, y, z, np.ones_like(x)])

def normalize(vec):
    return vec / np.linalg.norm(vec)

def project_vector(x, y, z, matrix):
    vec = np.dot(matrix, pad_ones(x, y, z))

    return vec[0]/vec[3], vec[1]/vec[3], vec[2]/vec[3]

def get_look_at_matrix(eye, center, up):
    n = normalize(eye - center)
    u = normalize(np.cross(up, n))
    v = np.cross(n, u)

    matrix_r = [[u[0], u[1], u[2], 0],
                [v[0], v[1], v[2], 0],
                [n[0], n[1], n[2], 0],
                [0,    0,    0,    1]]

    matrix_t = [[1, 0, 0, -eye[0]],
                [0, 1, 0, -eye[1]],
                [0, 0, 1, -eye[2]],
                [0, 0, 0, 1]]

    return np.dot(matrix_r, matrix_t)

def get_perspective_matrix(fovy, aspect, near, far):
    f = 1. / tan(fovy * pi / 360.)

    return np.array([
        [f/aspect, 0,                           0,                           0],
        [       0, f,                           0,                           0],
        [       0, 0,   (near + far)/(near - far), 2 * near * far/(near - far)],
        [       0, 0,                          -1,                           0]
    ])

class OrbitCamera():

    def __init__(self, radius, center, aspect, near=0, far=8):
        self.radius = radius
        self.center = np.array(center)
        self.aspect = aspect
        self.near = near
        self.far = far

        self.update_position(0, 0)

    def update_position(self, elev, azim):
        self.elev = elev
        self.azim = azim

        relev, razim = np.pi * self.elev/180, np.pi * self.azim/180

        xp = self.center[0] + cos(razim) * cos(relev) * self.radius
        yp = self.center[1] + sin(razim) * cos(relev) * self.radius
        zp = self.center[2] + sin(relev) * self.radius

        self.position = np.array((xp, yp, zp))
        self.front = self.center - self.position

        if abs(relev) > pi / 2.:
            self.up = np.array((0, 0, -1))
        else:
            self.up = np.array((0, 0, 1))

        self.update_matrix()

    def update_matrix(self):
        self.view_matrix = get_look_at_matrix(self.position, self.center, self.up)
        self.projection_matrix = get_perspective_matrix(50, self.aspect, self.near, self.far)
        self.matrix = np.dot(self.projection_matrix, self.view_matrix)


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

warnings.filterwarnings("ignore")

sns.set(color_codes=True)
# Reading the data where low_memory=False increases the program efficiency
data= pd.read_csv("gapminder.csv", low_memory=False)
# setting variables that you will be working with to numeric
data['breastcancerper100th']= data['breastcancerper100th'].convert_objects(convert_numeric=True)
data['femaleemployrate']= data['femaleemployrate'].convert_objects(convert_numeric=True)
data['alcconsumption']= data['alcconsumption'].convert_objects(convert_numeric=True)

#print "Showing missing data coulmn-wise"
#print data.isnull().sum()
# Create a copy of the original dataset as sub5 by using the copy() method
sub6=data.copy()
sub6_clean=sub6.dropna()

print("\nAssociation between alcohol consumption and breast cancer per 100th\n")
print(scipy.stats.pearsonr(sub6_clean['alcconsumption'], sub6_clean['breastcancerper100th']))

# using scatter plot the visulaize quantitative variable.
scat2= sns.regplot(x='alcconsumption', y='breastcancerper100th', data=sub6_clean)
plt.xlabel('Alcohol consumption in liters')
plt.ylabel('Breast cancer per 100th person')
plt.title('Scatterplot for the Association between Alcohol Consumption and Breast Cancer 100th person')


import numpy as np
from prml.nn.tensor.constant import Constant
from prml.nn.tensor.tensor import Tensor
from prml.nn.function import Function

class Sqrt(Function):
    """
    element-wise square root of the input
    y = sqrt(x)
    """

    def forward(self, x):
        x = self._convert2tensor(x)
        self.x = x
        self.output = np.sqrt(x.value)
        if isinstance(self.x, Constant):
            return Constant(self.output)
        return Tensor(self.output, function=self)

    def backward(self, delta):
        dx = 0.5 * delta / self.output
        self.x.backward(dx)

def sqrt(x):
    """
    element-wise square root of the input
    y = sqrt(x)
    """
    return Sqrt().forward(x)


import numpy as np
import warnings
from metrics import *

class SimpleLinearRegressor:

    def __init__(self):
        self.betas = None

    def predict(self, X, intercept=True):
        X = np.c_[np.ones(X.shape[0]), X] if intercept else X

        return np.dot(X, self.betas)

    def __ordinary_least_square(self, X, y, **kwargs):
        self.betas = np.dot(np.dot(np.linalg.inv(np.dot(X.T, X)), X.T), y)
        self.is_fitted = True

    def __gradient_descent(self, X, y, learning_rate, steps, seed, verbosity, cost_func='mse', **kwargs):
        np.random.seed(seed)

        minimize = {
            'mse': mean_squared_error,
            'mae': mean_absolute_error,

        }

        self.betas = np.random.rand(X.shape[1])

        for i in range(steps):
            try:
                predicted = self.predict(X, intercept=False)
            except TypeError as e:
                raise Exception('Model is not fitted. Call fit before predict').with_traceback(e.__traceback__)

            try:
                error = minimize.get(cost_func, lambda: 'Invalid')(predicted, y)
            except ValueError as e:
                raise Exception('X and y have different lenght')

            if verbosity != 0 and i % verbosity == 0 :
                print('Step: {} --- Error: {}'.format(i, error))

            error = absolute_error(predicted,  y)
            gradient = 2*np.dot(X.T, error) / len(X)
            self.betas -= learning_rate*gradient

    def fit(self, X, y, mode='ols', learning_rate=0.01, steps=10000, seed=0, verbosity=1000, cost_func='mse'):
        modes = {
            'ols': self.__ordinary_least_square,
            'gradient_descent': self.__gradient_descent
        }

        try:
            X = np.c_[np.ones(X.shape[0]), X]
        except AttributeError as e:
            raise Exception('X must a be an numpy array').with_traceback(e.__traceback__)

        try:
            modes.get(mode)(X=X,
                            y=y,
                            learning_rate=learning_rate,
                            steps=steps,
                            seed=seed,
                            verbosity=verbosity,
                            cost_func=cost_func)

        except TypeError as e:
            modes.get('ols')(X=X,
                            y=y)
            warnings.warn('Invalid parameter was used. Changing to ols and fitting model.'.format(mode))
        except Exception as e:
            raise e


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

import datetime

# Global variables
# speed
move_speed = 0.008

# mackey glass params
sigma = 10.0
phi = 28.0
beta = 8./3.

def runLorenz(num_data_samples=5000):
    # ------ better version on wikipedia which just solves the ODE----
    rho = 28.0
    sigma = 10.0
    beta = 8.0 / 3.0

    def f(state, t):
        x, y, z = state  # unpack the state vector
        # derivatives
        return sigma * (y - x), x * (rho - z) - y, x * y - beta * z

    delta_t = 0.01
    t_end = num_data_samples * delta_t
    state0 = [1.0, 1.0, 1.0]
    t = np.arange(0.0, t_end, delta_t)

    states = odeint(f, state0, t)

    return states

def onExit(data, axis1=0, axis2=2):
    # save the data
    np.savetxt("data_{}.txt".format(datetime.date.today()), data,
               delimiter=",")

    # plot the data
    plt.plot(data[:, axis1], data[:, axis2], linewidth=0.4)
    plt.xlabel("{}".format(axis1))
    plt.ylabel("{}".format(axis2))
    plt.show()

def d_x(x_t, y_t, z_t):
    return sigma * (y_t - x_t)

def d_y(x_t, y_t, z_t):
    return x_t * (phi - z_t) - y_t

def d_z(x_t, y_t, z_t):
    return x_t * y_t - beta * z_t

if __name__ == "__main__":
    data = runLorenz(num_data_samples=20000)
    onExit(data)


#!/usr/bin/env python

# Programmer(s): Sopan Patil.
# This file is part of the 'hydroutils' package.

import numpy

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

class ObjectiveFunction(object):

    """ The 'ObjectiveFunction' class contains the following two commonly used objective functions:
    (1) Kling-Gupta efficiency

    (2) Nash-Sutcliffe efficiency

    """

    @staticmethod
    def klinggupta(obsdata, simdata):

        """ This method calculates Kling-Gupta efficiency
        of the simulated data timeseries.

        Args:
            (1) obsdata: Time series of the observed data.

            (2) simdata: Time series of the simulated data.

        """

        xbar = numpy.mean(obsdata)
        ybar = numpy.mean(simdata)
        nobs = obsdata.shape[0]

        numer = numpy.sum(numpy.multiply(obsdata - xbar, simdata - ybar))
        denom1 = numpy.sum(numpy.square(obsdata - xbar))
        denom2 = numpy.sum(numpy.square(simdata - ybar))

        if denom2 == 0:
            kge = -9999
            return kge

        r = numer/(numpy.sqrt(denom1)*numpy.sqrt(denom2))
        alpha = numpy.sqrt(denom2/nobs)/numpy.sqrt(denom1/nobs)
        beta = ybar/xbar
        kge = 1.0 - numpy.sqrt(numpy.square(r-1.0) + numpy.square(alpha-1.0) + numpy.square(beta-1.0))
        return kge

    # ----------------------------------------------------------------

    @staticmethod
    def nashsutcliffe(obsdata, simdata):

        """ This method calculates Nash-Sutcliffe efficiency
        of the simulated data timeseries.

        Args:
            (1) obsdata: Time series of the observed data.

            (2) simdata: Time series of the simulated data.

        """

        numer = numpy.sum(numpy.square(obsdata - simdata))
        denom = numpy.sum(numpy.square(obsdata - numpy.mean(obsdata)))

        nse = 1.0 - (numer/denom)
        return nse

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


import formulas as f
import numpy as np

# Task 1
print("Task 1")

s = np.array([7.0, 7.3, 7.7, 8.1, 8.4, 8.8])
s *= 0.01
in_years = 4

print("Discount rate in {} years is {}".format(in_years, round(f.discount_rate(s[in_years-1], in_years), 3)))

# Task 2
print()
print("Task 2")
s = np.array([7.0, 7.3, 7.7, 8.1, 8.4, 8.8])
s *= 0.01
years = 6

print("Interest rate for {} years of a swap is {}%".format(years, round(100*f.swap_int_rate(s, years), 2)))

# Task 3
print()
print("Task 3")
print("Solution: 118.65")

# Task 4
print()
print("Task 4")
need_contracts = 10
orange_std = 0.2
grape_std = 0.25
corr = 0.7
hedge_ratio = f.futures_hedge_ratio(corr, orange_std, grape_std)
print("Optimal hedging ratio is {}".format(hedge_ratio))
print("Number of contracts to buy is {}".format(round(hedge_ratio*need_contracts, 0)))

# Task 5
print()
print("Task 5")
S0 = 100
u = 1.05
d = 1/u
R = 1.02
K = 102

print("The value of European call option on the stock with strike {} and given parameters"
      "\nS0 = {}"
      "\nu = {}"
      "\nd = {}"
      "\nR = {}"
      "\nis {}".format(K, S0, u, d, R, round(f.options_binomial_model(S0, u, d, R, K), 2)))

# Task 6
print()
print("Task 6")
print("Solution: y in Task 5")


import sympy as sy
from sympy.abc import a,c,b
import matplotlib.pyplot as plt
import numpy as np

def consum_function_plot(function):
    u = function #Original function
    u1d = function.diff(c) #1st derivative
    u2d = function.diff(c,c) #2nd derivative
    u_func, u1d_func, u2d_func = [sy.lambdify((a,c),x) for x in [u, u1d, u2d]] #Convert to lambda functions

    #Numerically solve functions
    x = np.linspace(0,10,101)
    solu_all = []
    for func in [u_func, u1d_func, u2d_func]:
        solu_single = [] #Creates nested list
        for i in x:
            solu_single.append(func(1,i)) #appends to nested list
        solu_all.append(solu_single) #appends nested list to all list

    #Graph
    plt.plot(x,solu_all[0], label='U(c)')
    plt.plot(x,solu_all[1], label=r'$U\prime$')
    plt.plot(x, solu_all[2], label=r'$U\prime\prime$')
    plt.ylabel('U(c)')
    plt.xlabel('c')
    plt.axhline(u_func(1,0), color='red', label=r"$\frac{-1}{a}$")
    plt.legend();

def consum_function_solver(function, time=np.array([1,2])):
    #Functions
    u = function #Original function
    u1d = function.diff(c) #1st derivative
    u2d = function.diff(c,c) #2nd derivative
    u_func, u1d_func, u2d_func = [sy.lambdify((a,c),x) for x in [u, u1d, u2d]] #Convert to lambda functions

    #Numerically solve functions
    x = time
    solu_all = []
    for func in [u_func, u1d_func, u2d_func]:
        solu_single = [] #Creates nested list
        for i in x:
            solu_single.append(func(1,i)) #appends to nested list
        solu_all.append(solu_single) #appends nested list to all list

    return solu_all

def power_euler_nograph(beta=False, r=False, sigma=False):

    beta_r = beta*(1+r)
    euler_rhs = beta_r**sigma

    y1, y2 = [10,10]
    h = y1+(y2/(1+r))
    c1 = h/(1+(beta**sigma*(1+r)**(sigma-1)))
    c2 = (beta*(1+r)**sigma)*(c1)
    return list([c1, c2, euler_rhs])


### Задание 3. Min smooth functions
# f(x) = sin(x / 5) * exp(x / 10) + 5 * exp(-x / 2), на промежутке [1, 30]

import numpy as np
from scipy.optimize import minimize
from plotly.offline import download_plotlyjs, plot, iplot
import plotly
import plotly.graph_objs as go
import math

#1. Попробуйте найти минимум, используя стандартные параметры в функции scipy.optimize.minimize
# (т.е. задав только функцию и начальное приближение).
# Попробуйте менять начальное приближение и изучить, меняется ли результат

def f(x):
    return (math.sin(x/5.)*math.exp(x/10.)+5*math.exp(-x/2.))

f_min1=minimize(f,30)
print ('x=30:', f_min1, '\n')

# 2. Укажите в scipy.optimize.minimize в качестве метода BFGS (один из самых точных в большинстве случаев градиентных методов оптимизации),
# запустите из начального приближения x=2.
# Градиент функции при этом указывать не нужно – он будет оценен численно.
f_min2=minimize(f,2, method = 'BFGS')
print ('x=2:',f_min2, '\n')

# 3. Теперь измените начальное приближение на x=30.
f_min3=minimize(f,30, method = 'BFGS')
print ('x=30:',f_min3,'\n')

# 4. Построение графика

x=np.arange(1,31,0.1)
trace=go.Scatter(
    x=x,
    y=list(map(f,x))
)
fig=go.Figure(data=[trace])
iplot(fig, show_link=False)
plot(fig, filename="min_smoothness.html", show_link=False)


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

# Adapted to use numpy array as entry from https://github.com/chncyhn/simulated-annealing-tsp

class SimAnneal(object):
    def __init__(self, Mw, T=-1, alpha=-1, stopping_T=-1, stopping_iter=-1):
        self.N = Mw.shape[0]
        self.T = math.sqrt(self.N) if T == -1 else T
        self.alpha = 0.995 if alpha == -1 else alpha
        self.stopping_temperature = 0.00000001 if stopping_T == -1 else stopping_T
        self.stopping_iter = 100000 if stopping_iter == -1 else stopping_iter
        self.iteration = 1

        self.dist_matrix = Mw
        self.nodes = [i for i in range(self.N)]

        self.cur_solution = self.initial_solution()
        self.best_solution = list(self.cur_solution)

        self.cur_fitness = self.fitness(self.cur_solution)
        self.initial_fitness = self.cur_fitness
        self.best_fitness = self.cur_fitness

        self.fitness_list = [self.cur_fitness]

    def initial_solution(self):
        """
        Greedy algorithm to get an initial solution (closest-neighbour)
        """
        cur_node = random.choice(self.nodes)
        solution = [cur_node]
        free_list = list(self.nodes)
        free_list.remove(cur_node)

        while free_list:
            closest_dist = np.amin(self.dist_matrix[cur_node,free_list])
            #np.where returns a list with indexes containing the closest_dist (which may be duplicated), intersect that with indexes still available (free_list) and get the first index available containing the closest_dist
            cur_node = np.intersect1d(np.where(self.dist_matrix[cur_node] == closest_dist)[0], np.array(free_list))[0]
            free_list.remove(cur_node)
            solution.append(cur_node)

        return solution

    def fitness(self, sol):
        """ Objective value of a solution """
        return round(sum([self.dist_matrix[sol[i - 1],sol[i]] for i in range(1, self.N)]) +
                     self.dist_matrix[sol[self.N - 1],sol[0]], 6)

    def p_accept(self, candidate_fitness):
        """
        Probability of accepting if the candidate is worse than current
        Depends on the current temperature and difference between candidate and current
        """
        return math.exp(-abs(candidate_fitness - self.cur_fitness) / self.T)

    def accept(self, candidate):
        """
        Accept with probability 1 if candidate is better than current
        Accept with probabilty p_accept(..) if candidate is worse
        """
        candidate_fitness = self.fitness(candidate)
        if candidate_fitness < self.cur_fitness:
            self.cur_fitness = candidate_fitness
            self.cur_solution = candidate
            if candidate_fitness < self.best_fitness:
                self.best_fitness = candidate_fitness
                self.best_solution = candidate

        else:
            if random.random() < self.p_accept(candidate_fitness):
                self.cur_fitness = candidate_fitness
                self.cur_solution = candidate

    def anneal(self):
        """
        Execute simulated annealing algorithm
        """
        while self.T >= self.stopping_temperature and self.iteration < self.stopping_iter:
            candidate = list(self.cur_solution)
            l = random.randint(2, self.N - 1)
            i = random.randint(0, self.N - l)
            candidate[i:(i + l)] = reversed(candidate[i:(i + l)])
            self.accept(candidate)
            self.T *= self.alpha
            self.iteration += 1
            self.fitness_list.append(self.cur_fitness)


import numpy as np

def f(x):
    return 20*x**1.5+np.exp(-x/5)

n=int(input("Number of panels: "))
sum = float()
if n%2!=0:
    print("Error.")
    quit()
else:
    x1=float(input("xmin: "))
    x2=float(input("xmax: "))
    h = (x2 - x1) / n
    for i in range(0,n):
        if i==0:
            x = x1
            y = f(x)
            sum = y
            print("x:","%.5f" % x); print("y:","%.5f" % y); print()
        else:
            x = x1 + h*i
            y = f(x)
            if i%2==0:
                sum = sum + 2*y
            else:
                sum = sum + 4*y
            print("x:","%.5f" % x); print("y:","%.5f" % y); print()
    x = x2
    y = f(x)
    sum = sum + y
    print("x:","%.5f" % x); print("y:","%.5f" % y); print()
    sum = h * sum/3
    print("SUM=","%.5f" % sum)


"""
Some study code for BSpline operation

Ref:
    [1] L. Biagiotti and C. Melchiorri, Trajectory Planning for Automatic Machines and Robots. 2008.
"""

import os
import sys

sys.path.append(os.path.abspath(os.path.join(__file__, os.pardir)))
sys.path.append(os.path.abspath(os.path.join(__file__, os.pardir, os.pardir)))

import argparse
import numpy as np
import matplotlib.pyplot as plt
import util

# class BSpline:
#     """
#     BSpline
#     """

#     def __init__(self, degree:)

def basic(knots: np.ndarray, degree: int, u: float, index: int):
    """
    Calculate the basic function in BSpline, N(i, p, u)

    Args:
        knots (np.ndarray): Knots vector {u}
        degree (int): Degree p
        u (float): Evaluate input u
        index (int): The index of u, i

    Returns:
        float: Basic function result evaluated at u
    """
    if degree == 0:
        return 1.0 if knots[index] <= u < knots[index + 1] else 0.0

    if knots[index] > u or u >= knots[index + degree + 1]:
        return 0

    c1 = (u - knots[index]) / (knots[index + degree] - knots[index]) if knots[index] <= u < knots[index +
                                                                                degree] else 0.0
    c2 = (knots[index + degree + 1] - u) / (
        knots[index + degree + 1] - knots[index + 1]) if knots[index + 1] <= u < knots[index + degree + 1] else 0.0
    return c1 * basic(knots, degree - 1, u, index) + c2 * basic(knots, degree - 1, u, index + 1)

def bspline(knots: np.ndarray, ctrl_points: np.ndarray, degree: int, u: float):
    """
    Evaluate BSpline function at u

    Args:
        knots (np.ndarray): Knots vector {u}
        ctrl_points (np.ndarray): Control points {P}
        degree (int): Degree p
        u (float): Evaluate input u
    Returns:
        np.ndarray:
    """
    s = np.zeros(ctrl_points.shape[0])
    for m in range(ctrl_points.shape[0]):
        for n in range(ctrl_points.shape[1]):
            s[m] += basic(knots, degree, u, n) * ctrl_points[m, n]
    return s

def cal_basic():
    """
    Calculate the basic function
    """
    print(util.Section('Basic Function'))

    # evaluate of degree 1
    knots = np.array([0.0, 0, 1, 2, 4, 7, 7])
    degree = 1
    u_array = np.arange(knots.min(), knots.max(), 0.01)
    basic_array = np.zeros([7, u_array.shape[0]])
    for n, u in enumerate(u_array):
        for j in range(0, basic_array.shape[0]):
            basic_array[j, n] = basic(knots, degree, u, j)
    # plot
    fig = plt.figure(f'Basic Function of Degree {degree}')
    ax = fig.add_subplot(111)
    ax.grid(True)
    for j in range(0, basic_array.shape[0]):
        ax.plot(u_array, basic_array[j, :], label=f'$B_{{{j}{degree}}}$')
    ax.legend(loc='best')
    ax.set_title(f'Basic function of Degree 1 Defined on u = {knots}')

    # evaluate of degree 3
    knots = np.array([0.0, 0, 0, 0, 1, 2, 4, 7, 7, 7, 7])
    degree = 3
    u_array = np.arange(knots.min(), knots.max(), 0.01)
    basic_array = np.zeros([7, u_array.shape[0]])
    for n, u in enumerate(u_array):
        for j in range(0, basic_array.shape[0]):
            basic_array[j, n] = basic(knots, degree, u, j)
    # plot
    fig = plt.figure(f'Basic Function of Degree {degree}')
    ax = fig.add_subplot(111)
    ax.grid(True)
    for j in range(0, basic_array.shape[0]):
        ax.plot(u_array, basic_array[j, :], label=f'$B_{{{j}{degree}}}$')
    ax.legend(loc='best')
    ax.set_title(f'Basic function of Degree 1 Defined on u = {knots}')

def cal_bspline():
    """
    Calculate the BSpline function
    """
    print(util.Section('BSpline Function'))

    # Evaluation case 1
    knots = np.array([0.0, 0, 0, 0, 1, 2, 4, 7, 7, 7, 7.0])
    ctrl_points = np.array([[1, 2, 3, 4, 5, 6, 7], [2, 3, -3, 4, 5, -5, -6]])
    degree = 3
    u_array = np.arange(knots.min(), knots.max(), 0.01)
    bspline_array = np.zeros([ctrl_points.shape[0], u_array.shape[0]])
    for n, u in enumerate(u_array):
        bspline_array[:, n] = bspline(knots, ctrl_points, degree, u)
    # plot
    fig = plt.figure(f'Basic Function of Degree {degree} - Case 1')
    ax = fig.add_subplot(111)
    ax.grid(True)
    ax.plot(ctrl_points[0, :], ctrl_points[1, :], 'o--')
    ax.plot(bspline_array[0, :], bspline_array[1, :])
    ax.set_title(f'BSpline function of Degree {degree} Defined on u = {knots}')

    # Evaluation case 2, double the knots in case 1
    knots2 = 2 * knots
    ctrl_points = np.array([[1, 2, 3, 4, 5, 6, 7], [2, 3, -3, 4, 5, -5, -6]])
    degree = 3
    u_array2 = np.arange(knots2.min(), knots2.max(), 0.01)
    bspline_array2 = np.zeros([ctrl_points.shape[0], u_array2.shape[0]])
    for n, u in enumerate(u_array2):
        bspline_array2[:, n] = bspline(knots2, ctrl_points, degree, u)
    # plot
    fig = plt.figure(f'Basic Function of Degree {degree} - Double the Knots')
    ax = fig.add_subplot(111)
    ax.grid(True)
    ax.plot(u_array, bspline_array[0, :], label='BSpline1[0]')
    ax.plot(u_array, bspline_array[1, :], label='BSpline1[1]')
    ax.plot(u_array2, bspline_array2[0, :], label='BSpline2[0]')
    ax.plot(u_array2, bspline_array2[1, :], label='BSpline2[1]')
    ax.legend(loc='best')
    ax.set_title(f'BSpline function of Degree {degree} Defined on u = {knots}')

    # Evaluation case 3
    knots = np.array([0.0, 0, 0, 0, 2, 2, 2, 7, 7, 7, 7.0])
    ctrl_points = np.array([[1, 2, 3, 4, 5, 6, 7], [2, 3, -3, 4, 5, -5, -6]])
    degree = 3
    u_array = np.arange(knots.min(), knots.max(), 0.01)
    bspline_array = np.zeros([ctrl_points.shape[0], u_array.shape[0]])
    for n, u in enumerate(u_array):
        bspline_array[:, n] = bspline(knots, ctrl_points, degree, u)
    # plot
    fig = plt.figure(f'Basic Function of Degree {degree} - Case 3')
    ax = fig.add_subplot(111)
    ax.grid(True)
    ax.plot(ctrl_points[0, :], ctrl_points[1, :], 'o--')
    ax.plot(bspline_array[0, :], bspline_array[1, :], label='BSpline1')
    ax.legend(loc='best')
    ax.set_title(f'BSpline function of Degree {degree} Defined on u = {knots}')

    # Evaluation case 4, for different degree
    knots = np.array([0.0, 0, 0, 0, 1, 2, 4, 7, 7, 7, 7])
    ctrl_points = np.array([[1, 2, 3, 4, 5, 6, 7], [2, 3, -3, 4, 5, -5, -6]])
    degree = 3
    u_array = np.arange(knots.min(), knots.max(), 0.01)
    bspline_array = np.zeros([ctrl_points.shape[0], u_array.shape[0]])
    bspline_array2 = np.zeros([ctrl_points.shape[0], u_array.shape[0]])
    bspline_array3 = np.zeros([ctrl_points.shape[0], u_array.shape[0]])
    for n, u in enumerate(u_array):
        bspline_array[:, n] = bspline(knots, ctrl_points, degree, u)
        bspline_array2[:, n] = bspline(knots, ctrl_points, degree - 1, u)
        bspline_array3[:, n] = bspline(knots, ctrl_points, degree - 2, u)
    # plot
    fig = plt.figure(f'Basic Function of Degree {degree} to {degree-2} - Case 3')
    ax = fig.add_subplot(111)
    ax.grid(True)
    ax.plot(ctrl_points[0, :], ctrl_points[1, :], 'o--')
    ax.plot(bspline_array[0, :], bspline_array[1, :], label='BSpline1')
    ax.plot(bspline_array2[0, :], bspline_array2[1, :], label='BSpline2')
    ax.plot(bspline_array3[0, :], bspline_array3[1, :], label='BSpline3')
    ax.legend(loc='best')
    ax.set_title(f'BSpline function of Degree {degree} to {degree-2} Defined on u = {knots}')

def main():
    # cal_basic()
    cal_bspline()
    plt.show(block=True)

if __name__ == "__main__":
    main()


from __future__ import division
from scipy import *
from pylab import *

from scipy import signal

T=2.0
#T=10.0
fs=100
dt=1.0/fs
t=arange(0.0,T,dt)#create the time vector
u=where(t>0.5,1,0)#create the step input vector

ylim([-0.1,1.1])
#mysys=signal.lti(1,[1,0])
p=4.0*2*pi
mysys=signal.lti(p,[1,p])#this line defines a transfer function
yo=signal.lsim2(mysys,u,t)#this line simulates the output of the system based on input u and time t
u=squeeze(u)
figure(1)
cla()
plot(t,u,t,yo[1])
legend(['input','output'],2)
xlabel('Time (sec)')
ylabel('Amplitude')
title('Step Response')

df=1.0/T#(t.max()-t.min())
f=arange(0,fs,df)

s=2.0j*pi*f

#tf=1.0/s

N=len(f)

def bodeplot(fi,f,tf,clear=True):
    figure(fi)
    if clear:
        clf()
    subplot(211)
    semilogx(f,20*log10(abs(tf)))
    ylabel('Mag. Ratio (dB)')
    subplot(212)
    semilogx(f,arctan2(imag(tf),real(tf))*180.0/pi)
    ylabel('Phase (deg.)')
    xlabel('Freq. (Hz)')

#################################
#
#    Swept Sine
#
#################################
def Usweep(ti,minf=0.0,maxf=10.0, maxt=max(t)):
    if ti<0.0:
        return 0.0
    else:
        curf=(maxf-minf)*ti/maxt+minf
        if ti<(maxt*0.95):
            return sin(2*pi*curf*ti)
        else:
            return 0.0

Uchirp=array([Usweep(ti) for ti in t])#this line defins a swept sine input
yc=signal.lsim2(mysys,Uchirp,t)#this line calculates the response to the swept sine input
Uchirp=squeeze(Uchirp)
yco=yc[1]

figure(3)
clf()
subplot(211)
plot(t,Uchirp)
ylabel('input u(t)')
title('Swept Sine Response')
subplot(212)
plot(t,yco)
ylabel('output y(t)')
xlabel('Time (sec)')

ycfft=fft(yco)*2/N
ucfft=fft(Uchirp)*2/N
tfc=ycfft/ucfft

tfcheck=p/(s+p)

bodeplot(4,f,tfc)
bodeplot(4,f,tfcheck,clear=False)

fN=f[int(N/2)]
subplot(211)
xlim([0.1,fN])
legend(['experiment','model'],3)
title('Bode Plot')

subplot(212)
xlim([0.1,fN])
ylim([-100,10])

show()


#!/usr/bin/env python2
# -*- coding: utf-8 -*-

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import scipy.stats as stats

times = pd.read_csv('servicetime_data.csv')
x = times['ser_time'].values
xvalues = list(x)

times.plot.hist(bins=150)
plt.xlabel('Service Time')
plt.ylabel('Frequency')
plt.show()

logx = np.log(x)

# MLE for Exponential:
rate = len(x)/float(x.sum()) # lambda = n/sum(x)
scale1 = 1.0/rate
loc = 0

# create a Q-Q plot
fig1 = stats.probplot(x, dist="expon", sparams=(loc,scale1), plot=plt)
plt.show()

# perform a goodness of fit test (K-S) test;
# null hyposthesis is that data is coming from the specified dist
GoF1 = stats.kstest(x, 'expon', args=(loc, scale1))
print GoF1

# MLE for Lognormal:
mu = logx.sum()/len(x)
sigma = np.sqrt(((logx-(logx.sum()/len(x)))**2).sum()/len(x))
shape2 = sigma
scale2 = np.exp(mu)
loc = 0

fig2 = stats.probplot(x, dist="lognorm", sparams=(shape2,loc,scale2), plot=plt)
plt.show()

GoF2 = stats.kstest(x, 'lognorm', args=(shape2, loc, scale2))
print GoF2

# Gamma:
# Since there is no closed form MLE for Gama, we fit a Gamma numerically
shape3, loc, scale3 = stats.gamma.fit(x, floc = 0)

fig3 = stats.probplot(x, dist="gamma", sparams=(shape3,loc,scale3), plot=plt)
plt.show()

GoF3 = stats.kstest(xvalues, 'gamma', args=(shape3, loc, scale3))
print GoF3

# Moments estimation for Gama:
beta = x.std()
alpha = x.mean()/x.std()


import numpy as np

def randInitializeWeights(L_in, L_out):
#RANDINITIALIZEWEIGHTS Randomly initialize the weights of a layer with L_in
#incoming connections and L_out outgoing connections
#   W = RANDINITIALIZEWEIGHTS(L_in, L_out) randomly initializes the weights
#   of a layer with L_in incoming connections and L_out outgoing
#   connections.
#
#   Note that W should be set to a matrix of size(L_out, 1 + L_in) as
#   the first row of W handles the "bias" terms
#

# You need to return the following variables correctly
    W = np.zeros((L_out, 1 + L_in))

# ====================== YOUR CODE HERE ======================
# Instructions: Initialize W randomly so that we break the symmetry while
#               training the neural network.
#
# Note: The first row of W corresponds to the parameters for the bias units

    epsilon = np.sqrt(6)/np.sqrt(L_out + L_in)
    s = np.random.uniform(-epsilon, epsilon, L_out * (1 + L_in))
    W = s.reshape(L_out, 1 + L_in)

#
# =========================================================================

    return W


import numpy as np

def featureScaling(X):
    """Scales features."""
    stdev_Of_Each_Feature = np.std(X, axis=0)
    mean_Of_Each_Feature = X.mean(0)
    scaled_X = (X - mean_Of_Each_Feature) / stdev_Of_Each_Feature

    """These are for checking.
    # range_Of_Features = np.ptp(X, axis=0)
    # mean_ = X.mean(0)
    # max_ = np.max(X, axis=0)
    # min_ = np.min(X, axis=0)
    # stdev = np.std(X, axis=0)
    """

    # scaled_X_ver2 = (X - mean_Of_Each_Feature) / range_Of_Features # This one is to test different scaling for features.
    # return scaled_X_ver2
    return scaled_X


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Tue Jul  9 11:48:56 2019

@author: fietekrutein

A script to solve an unconstrained problem using
steepest descent fradient search with exact line search
"""
import numpy as np
import matplotlib.pyplot as plt

# functions as per example problem

def obj(x,Q):
    return 0.5*np.matmul(x, np.matmul(Q,x))

def gx2(x,Q):
    return np.matmul(Q,x)

# method

def GradDescent2(x,Q,gx2,rec,tol=10e-5):
    xCurrent = x
    gxVal = gx2(xCurrent,Q)
    rec.append(obj(xCurrent,Q))
    while True:
        xNext = xCurrent - ((xCurrent[0]**2 + gamma[i]**2*xCurrent[1]**2)/
                            (xCurrent[0]**2 + gamma[i]**3*xCurrent[1]**2))*gxVal
        gxNextVal = gx2(xNext, Q)
        rec.append(obj(xNext,Q))

        if (np.linalg.norm(gxNextVal,2) <= tol) == True:
            break
        xCurrent = xNext
        gxVal = gxNextVal

    return xNext, rec

# initialize problem parameters
gamma = np.array([0.1, 1, 2, 10])
rec = np.empty(4, dtype=np.object)

# execute

for i in np.arange(0,4):
    x = np.array([gamma[i], 1])
    Q = np.array([[1,0],[0,gamma[i]]])
    rec[i] = []
    GradDescent2(x, Q, gx2, rec[i], tol=10e-5)

# plot

plt.subplot(2,2,1)
plt.plot(rec[0])
plt.xlabel('iterations')
plt.ylabel('objective value')
plt.subplot(2,2,2)
plt.plot(rec[1])
plt.xlabel('iterations')
plt.subplot(2,2,3)
plt.plot(rec[2])
plt.xlabel('iterations')
plt.ylabel('objective value')
plt.subplot(2,2,4)
plt.plot(rec[3])
plt.xlabel('iterations')

plt.show()


## module romberg
''' I,nPanels = romberg(f,a,b,tol=1.0e-6).
    Romberg intergration of f(x) from x = a to b.
    Returns the integral and the number of panels used.
'''
from numpy import zeros
from trapezoid import *

def romberg(f,a,b,tol=1.0e-6):

    def richardson(r,k):
        for j in range(k-1,0,-1):
            const = 4.0**(k-j)
            r[j] = (const*r[j+1] - r[j])/(const - 1.0)
        return r

    r = zeros(21)
    r[1] = trapezoid(f,a,b,0.0,1)
    r_old = r[1]
    for k in range(2,21):
        r[k] = trapezoid(f,a,b,r[k-1],k)
        r = richardson(r,k)
        if abs(r[1]-r_old) < tol*max(abs(r[1]),1.0):
            return r[1],2**(k-1)
        r_old = r[1]
    print("Romberg quadrature did not converge")

ExamPrep/SciCompComplete/Shit Comp/Cheat Sheet + Modules/romberg.py


"""
  Name     : c9_08_generate_2set_correlated_randomNumbers.py
  Book     : Python for Finance (2nd ed.)
  Publisher: Packt Publishing Ltd.
  Author   : Yuxing Yan
  Date     : 6/6/2017
  email    : yany@canisius.edu
             paulyxy@hotmail.com
"""

import scipy as sp
sp.random.seed(123)
n=1000
rho=0.3

x1=sp.random.normal(size=n)
x2=sp.random.normal(size=n)

y1=x1
y2=rho*x1+sp.sqrt(1-rho**2)*x2
print(sp.corrcoef(y1,y2))


import matplotlib.pyplot as plt
from numpy import loadtxt, zeros, ones, array, linspace, logspace
from pylab import scatter, show, title, xlabel, ylabel, plot, contour, legend
from LinearRegression import LinearRegression
import numpy as np
from matplotlib.colors import Normalize
from matplotlib import cm
from mpl_toolkits.mplot3d import axes3d, Axes3D

LR = LinearRegression()

def surf(Z, X, Y):

    C = Z

    scalarMap = cm.ScalarMappable(norm=Normalize(
        vmin=C.min(), vmax=C.max()), cmap=cm.jet)

    # outputs an array where each C value is replaced with a corresponding color value
    C_colored = scalarMap.to_rgba(C)

    fig = plt.figure()

    ax = Axes3D(fig)

    surf = ax.plot_surface(X, Y, Z, facecolors=C_colored)

    return surf

# ====================Part 1: Basic Function====================

print('Running warmUpExercise ...')
print('5x5 Identity Matrix:')
print(LR.warmupex())

input('Program paused. Press enter to continue.')

# ========================Part 2: Plotting======================

print('plotting data')
data = np.loadtxt('ex1data1.txt', delimiter=',')
datax = data[:, 0]
datay = data[:, 1]
m = len(datay)  # number of training examples
datax = data[:, 0].reshape((m, 1))
datay = data[:, 1].reshape((m, 1))
# LR.plotdata(datax, datay)

input('Program paused. Press enter to continue.')

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

# Add a column of ones to x

one = np.ones((m, 1))
datax = np.append(one, datax, axis=1)
print(datax)
print(datax.shape)
# initialize fitting parameters

theta = np.zeros((2, 1))

# Some gradient descent settings
alpha = 0.01
num_iters = 1500
print('Testing the cost function ...')

# compute and display initial cost

J = LR.computecost(datax, datay, theta)
print('With theta = [0 ; 0]Cost computed =', J)
print('Expected cost value (approx) 32.07')

# further testing of the cost function

thetatest = np.array([[-1], [2]])
J = LR.computecost(datax, datay, thetatest)
print('With theta = [-1 ; 2]Cost computed = ', J)
print('Expected cost value (approx) 54.24')

input('Program paused. Press enter to continue.')

# run gradient descent

print('Running Gradient Descent ...')
theta, J_history = LR.gradientdescent(datax, datay, theta, alpha, num_iters)
# plot(list(range(num_iters)), J_history)
# show()
# print theta to screen

print('Theta found by gradient descent:')
print('  ', theta)
print('Expected theta values (approx)')
print(' -3.6303  1.1664')

# Plot the linear fit
# hold on; % keep previous plot visible

scatter(datax[:, 1], datax.dot(theta))
xlabel('Training data')
ylabel('Linear regression')
show()

# Predict values for population sizes of 35, 000 and 70, 000
predict1 = np.dot([1, 3.5], theta)
print('For population = 35,000, we predict a profit of ', predict1*10000)
predict2 = np.dot([1, 7], theta)
print('For population = 70,000, we predict a profit of ', predict2*10000)

input('Program paused. Press enter to continue.')

# =============Part 4: Visualizing J(theta_0, theta_1)=============

print('Visualizing J(theta_0, theta_1) ')

# Grid over which we will calculate J

theta0_vals = np.linspace(-10, 10, 100)
theta1_vals = np.linspace(-1, 4, 100)

# initialize J_vals to a matrix of 0's

J_vals = zeros(shape=(theta0_vals.size, theta1_vals.size))

# Fill out J_vals

for i in range(0, len(theta0_vals)):

    for j in range(0, len(theta1_vals)):
        t = [[theta0_vals[i]], [theta1_vals[j]]]
        J_vals[i, j] = LR.computecost(datax, datay, t)

print(J_vals)

X, Y = np.meshgrid(theta0_vals, theta1_vals)

# Because of the way meshgrids work in the surf command, we need to
# transpose J_vals before calling surf, or else the axes will be flipped

J_vals = np.transpose(J_vals)

# Surface plot
surf(X=X, Y=Y, Z=J_vals)
fig2 = plt.figure(figsize=(6, 5))
# Contour plot

input('press enter ')

contour(theta0_vals, theta1_vals, J_vals, np.logspace(-2, 3, 20))
xlabel('theta_0')
ylabel('theta_1')
scatter(theta[0], theta[1])
show()

input('press inter ')

legend(loc='lower right')
show()
print(theta)


import numpy as np
from datetime import datetime
startTime = datetime.now()

max_prime = 2000000
primes = range(2,max_prime)
length = len(primes)

for idx in range(len(primes)):
    p = primes[idx]
    if p == 0:
        continue

    # No multiples of any prime is a prime
    for i in range(2, (length + 1) / p + 1):
        primes[p*i - 2] = 0

primes = [y for y in primes if y != 0]

print "Time to make list", datetime.now() - startTime

print 'sum_of_primes less than', max_prime,':', np.sum(primes)


import numpy as np
from sklearn.metrics import mean_squared_error

def rmse(y_true, y_pred):
    assert len(y_true) == len(y_pred)
    return np.sqrt(mean_squared_error(y_true, y_pred))

def multilabel_f1(y_true, y_pred):
    """

    Refer from @author: onodera @address: https://www.kaggle.com/onodera

    Multi-labels f1 score

    Parameters
    ----------
    y_true    : iterable object (list, array)
    y_pred    : iterable object (list, array)

    Returns
    -------

    Examples
    --------
    >>> y_true = [1, 2, 3]
    >>> y_pred = [2, 3]
    >>> multilabel_f1(y_true, y_pred)
    ... 0.8
    """
    y_true, y_pred = set(y_true), set(y_pred)
    precision = np.sum([1 for i in y_pred if i in y_true]) / len(y_pred)
    recall = np.sum([1 for i in y_true if i in y_pred]) / len(y_true)
    if precision + recall == 0:
        return 0
    else:
        return (2 * precision * recall) / (precision + recall)


# -*- coding: utf-8 -*-
"""
Created on Sat Jun  2 23:33:19 2018

@author: Marcus
"""

import numpy as np

def generate_W_N_table(N):
    """Generate a table of phase angles.

    Parameters
    ----------
    N : int
        The number of phase angles needed. Must be a power of 2.

    Returns
    -------
    np.array
        An array of the phase angles.
    """
    if((N % 2) != 0):
        raise ValueError("N must be a power of 2")

    elif(N <= 0):
        raise ValueError("N must be a positive integer")

    W_N = np.zeros(N, dtype=np.complex)

    W = np.exp(-1j * 2 * np.pi / N)

    for idx in range(N//2):
        W_N[idx] = np.power(W, idx)

    W_N[N//2:] = -1 * W_N[:N//2]

    return W_N

N = 4

x = np.random.normal(size=N)

W = generate_W_N_table(N)

X = np.fft.fft(x)

y = np.fft.ifft(X)

my_X = np.zeros(N, dtype=np.complex)
first_stage = np.zeros(N, dtype=np.complex)

#2-point DFTs
W_2 = np.array([W[0], W[0]])
a = x[0:2]
b = W_2 * x[2:4]

first_stage[0] = a[0] + b[0]
first_stage[1] = a[0] - b[0]
first_stage[2] = a[1] + b[1]
first_stage[3] = a[1] - b[1]

#4-point DFT
W_4 = np.array([W[0], W[1]])
A = first_stage[0:2]
B = W_4 * first_stage[2:4]

my_X[0] = A[0] + B[0]
my_X[1] = A[1] + B[1]
my_X[2] = A[0] - B[0]
my_X[3] = A[1] - B[1]

print(X)
print(my_X)
print(np.allclose(X, my_X))