import numpy as np
import pandas as pd
import datetime
import math

def combine_data(sales_df, weather_df):
    '''
    Combines sales date with weather data to fit models and get forecasts and predictions

    Input: Cleaned sales pandas data frame, cleaned weather pandas data frame

    Output: Pandas data frame
    '''
    # combine the sales and weather dataframes
    combined_df = sales_df.merge(weather_df, left_index=True, right_index=True)

    # create the sine and cosine vectors for each day of the year
    sin_vect = pd.Series(combined_df.index).apply(lambda x: assign_sine_vector(x))
    cos_vect = pd.Series(combined_df.index).apply(lambda x: assign_cosine_vector(x))
    sin_vect.index = combined_df.index
    cos_vect.index = combined_df.index

    # add sine vector series to the dataframe
    combo_with_sin_df = pd.concat([combined_df, sin_vect], axis=1)
    combo_with_sin_df.rename(columns={'date': 'sin_vect'}, inplace=True)

    # add cosine vector series to the dataframe
    combo_with_cos_df = pd.concat([combo_with_sin_df, cos_vect], axis=1)
    combo_with_cos_df.rename(columns={'date': 'cos_vect'}, inplace=True)

    # create dummies out of the days of the week, and add dummies to the dataframe
    day_of_week = combined_df['day_of_week']
    days = pd.get_dummies(day_of_week)
    combo_dummy_days_df = pd.concat([combo_with_cos_df, days], axis=1)
    transformed_df = combo_dummy_days_df.drop(columns=['day_of_week'], axis=1)

    # create columns for 2 week rolling averages to include recent sales
    # as features
    wd = combo_with_cos_df['day_of_week'].nunique()
    transformed_df['rolling_{}'.format(str(2 * wd))] = transformed_df['net_sales'].rolling(2*wd).mean()

    # drop the rows that have rolling averages with NaNs
    return transformed_df[(2 * wd - 1):]

def date_to_nth_day(date):
    '''
    Function to convert a datetime day to a number

    Input: datetime date ie datetime(y, m, d)

    Output: int
    '''
    date = pd.to_datetime(date)
    new_year_day = pd.Timestamp(year=date.year, month=1, day=1)
    return (date - new_year_day).days + 1

def assign_sine_vector(date):
    '''
    Function will create a sine vector based on the day of the year (d) such that
    vector = sin((2 * pi * d) / 365

    Input: datetime date ie datetime(y, m, d)

    Output: sine vector
    '''
    return math.sin((2 * math.pi * date_to_nth_day(date)) / 365)

def assign_cosine_vector(date):
    '''
    Function will create a cosine vector based on the day of the year (d) such that
    vector = cos((2 * pi * d) / 365

    Input: datetime date ie datetime(y, m, d)

    Output: cosine vector
    '''
    return math.cos((2 * math.pi * date_to_nth_day(date)) / 365)


# -*- coding: utf-8 -*-
"""
computes the MFCCs from the magnitude spectrum (see Slaney)

  Args:
    X: spectrogram (dimension FFTLength X Observations)
    f_s: sample rate of audio data

  Returns:
    v_mfcc mel frequency cepstral coefficients
"""

import numpy as np
from ToolMfccFb import ToolMfccFb

def FeatureSpectralMfccs(X,f_s, iNumCoeffs = 13):

    # allocate memory
    v_mfcc = np.zeros ([iNumCoeffs, X.shape[1]])

    # generate filter matrix
    H = ToolMfccFb(X.shape[0], f_s)
    T = generateDctMatrix (H.shape[0], iNumCoeffs)

    for n in range(0,X.shape[1]):
        # compute the mel spectrum
        X_Mel = np.log10(np.dot(H, X[:,n] + 1e-20))

        # calculate the mfccs
        v_mfcc[:,n] = np.dot(T, X_Mel)

    return (v_mfcc)

# see function mfcc.m from Slaneys Auditory Toolbox
def generateDctMatrix (iNumBands, iNumCepstralCoeffs):
    T = np.cos(np.outer(np.arange(0,iNumCepstralCoeffs), (2*np.arange(0,iNumBands)+1)) * np.pi/2/iNumBands)

    T = T / np.sqrt(iNumBands/2)
    T[0,:] = T[0,:] / np.sqrt(2)

    return (T)


import numpy as np
import numpy.linalg as LA
import math as m

def gaussianKernel(x1, x2, sigma):
    """returns a gaussian kernel between x1 and x2
    and returns the value in sim
    """
    # RBF Kernel
    return m.exp(-(LA.norm(x1.ravel() - x2.ravel())**2)/(2*sigma**2))


import os
import numpy as np

def get_lrt_folder():
    user_location = os.path.expanduser('~/.pylrtrc')
    try:
        with open(user_location, 'r') as f:
            return f.read().strip()
    except FileNotFoundError:
        raise FileNotFoundError('No default location for LibRadTran found. Place the path in ~/.pylrtrc.')

def planck_function(temperature, wavelength=None, frequency=None, wavenumber=None):
    '''Supply one of wavelength in m, frequency in Hz, wavenumber in m-1'''
    import scipy.constants
    h = scipy.constants.h
    c = scipy.constants.c
    kb = scipy.constants.Boltzmann
    if wavelength is not None:
        return ((2*h*c**2)/(wavelength**5))*(1/(np.exp(h*c/(kb*temperature*wavelength))-1))
    elif frequency is not None:
        return ((2*h*frequency**3)/(c**2))*(1/(np.exp(h*frequency/(kb*temperature))-1))
    elif wavenumber is not None:
        return ((2*h*c**2*wavenumber**3))*(1/(np.exp(h*c*wavenumber/(kb*temperature))-1))


from sympy import *
x = Symbol('x')
# y = solve(x**4 - 4*x -1, x)
# print(N(y[1])*(-1)**0.5)
# print((-1)**0.5)

ns =1.5
zeta = 0.15
famp = 7
fmean = 11
sse = 56861.6
sut = 284306.60
d = 0.0915
# temp = ns*2*(1+zeta)*(famp/se  + fmean/sy)
# eqn  = 4*(x**2)*temp + 2*temp*x-4*x+3
eqn = (((4*x+2)*8*(1+zeta)*x*ns)/(pi*d*d))*(famp/sse+fmean/sut)+3-4*x

c = solve(eqn, x)
for tt in c:
  print(N(tt))


import numpy as np
import matplotlib.pyplot as plt
import math
from BSplineBasis import CoxDeBoorRecursion, BasisGraph
from KnotVectors import OpenUniformKnotVector
from BSpline import BSpline

def CoxDeBoorFirstDerivative(i, order, Knots, t):
    if order == 1:
        return 0.
    else:
        ftt = CoxDeBoorRecursion(i, order - 1, Knots, t) + (t - Knots[i]) * CoxDeBoorFirstDerivative(i, order - 1, Knots, t)
        ftb = Knots[i + order - 1] - Knots[i]
        stt = (Knots[i + order] - t) * CoxDeBoorFirstDerivative(i + 1, order - 1, Knots, t) - CoxDeBoorRecursion(i + 1, order - 1, Knots, t)
        stb = Knots[i + order] - Knots[i + 1]

        first = ftt / ftb
        if math.isnan(first):
            first = 0.

        second = stt / stb
        if math.isnan(second):
            second = 0.

        return first + second

def CoxDeBoorSecondDerivative(i, order, Knots, t):
    if order <= 2:
        return 0.
    else:
        ftt = 2 * CoxDeBoorFirstDerivative(i, order - 1, Knots, t) + (t - Knots[i]) * CoxDeBoorSecondDerivative(i, order - 1, Knots, t)
        ftb = Knots[i + order - 1] - Knots[i]
        stt = (Knots[i + order] - t) * CoxDeBoorSecondDerivative(i + 1, order - 1, Knots, t) - 2 * CoxDeBoorFirstDerivative(i + 1, order - 1, Knots, t)
        stb = Knots[i + order] - Knots[i + 1]

        first = ftt / ftb
        if math.isnan(first):
            first = 0.

        second = stt / stb
        if math.isnan(second):
            second = 0.

        return first + second

def BasisFirstDerivativeGraph(Knots, order, i, T):
    values = []
    for t in T:
        values.append(CoxDeBoorFirstDerivative(i, order, Knots, t))
    return np.asarray(values)

def BasisSecondDerivativeGraph(Knots, order, i, T):
    values = []
    for t in T:
        values.append(CoxDeBoorSecondDerivative(i, order, Knots, t))
    return np.asarray(values)

def BSplineFirstDerivative(Points, order, Knots, T):
    countPoints = np.size(Points, 0)
    n = countPoints - 1
    dimension = np.size(Points, 1)
    rVal = []
    for t in T:
        point = np.zeros(dimension)
        for i in range(0, n+1):
            point += Points[i] * CoxDeBoorFirstDerivative(i, order, Knots, t)
        rVal.append(point)
    return np.array(rVal)

def BSplineSecondDerivative(Points, order, Knots, T):
    countPoints = np.size(Points, 0)
    n = countPoints - 1
    dimension = np.size(Points, 1)
    rVal = []
    for t in T:
        point = np.zeros(dimension)
        for i in range(0, n+1):
            point += Points[i] * CoxDeBoorSecondDerivative(i, order, Knots, t)
        rVal.append(point)
    return np.array(rVal)

def BSplineTangent(Points, order, Knots, t):
    deriv = BSplineFirstDerivative(Points, order, Knots, [t])[0]
    point = BSpline(Points, order, Knots, [t])[0]
    norm = deriv / np.linalg.norm(deriv)
    points = []
    points.append(point + norm)
    points.append(point - norm)
    points = np.asarray(points)
    return points

if __name__ == "__main__":
    order = 4
    countPoints = 6
    Knots = OpenUniformKnotVector(order, countPoints, False)

    maxKnot = np.max(Knots)

    T = np.arange(0., maxKnot, 0.01)

    for i in range(countPoints):
        plt.plot(T, BasisGraph(Knots, order, i, T))

    plt.show()

    for i in range(countPoints):
        plt.plot(T, BasisFirstDerivativeGraph(Knots, order, i, T))

    plt.show()

    for i in range(countPoints):
        plt.plot(T, BasisSecondDerivativeGraph(Knots, order, i, T))

    plt.show()

    BoxOrder = 3
    BoxPoints = np.array([[2, 0], [4, 0], [4, 2], [4, 4], [2, 4], [0, 4], [0, 2], [0, 0], [2, 0]])
    BoxKnots = OpenUniformKnotVector(BoxOrder, np.size(BoxPoints, 0), True)
    BoxT = np.arange(0., 1., 0.01)

    BoxSpline = BSpline(BoxPoints, BoxOrder, BoxKnots, BoxT)
    BoxFirstDerivative = BSplineFirstDerivative(BoxPoints, BoxOrder, BoxKnots, BoxT)
    BoxSecondDerivative = BSplineSecondDerivative(BoxPoints, BoxOrder, BoxKnots, BoxT)

    plt.plot(BoxPoints[:, 0], BoxPoints[:, 1])
    plt.plot(BoxSpline[:, 0], BoxSpline[:, 1])
    plt.plot(BoxFirstDerivative[:, 0], BoxFirstDerivative[:, 1])
    plt.plot(BoxSecondDerivative[:, 0], BoxSecondDerivative[:, 1])

    plt.show()

    BoxTangent = BSplineTangent(BoxPoints, BoxOrder, BoxKnots, 0.4)
    plt.plot(BoxPoints[:, 0], BoxPoints[:, 1])
    plt.plot(BoxSpline[:, 0], BoxSpline[:, 1])
    plt.plot(BoxTangent[:, 0], BoxTangent[:, 1])

    plt.show()


import math
import numpy as np

# https://cs.brown.edu/research/pubs/pdfs/1999/Moller-1999-EBA.pdf
def get_rotation_matrix(f, t):
    """Get rotation matrix from one vector (f) to another (t)"""
    v = np.cross(f, t)
    u = v / np.linalg.norm(v)
    c = np.dot(f, t)
    h = (1 - c) / (1 - (c ** 2))
    vx, vy, vz = v
    rotation_matrix = [
            [c + h*vx**2, h*vx*vy - vz, h*vx*vz + vy],
            [h*vx*vy+vz, c+h*vy**2, h*vy*vz-vx],
            [h*vx*vz - vy, h*vy*vz + vx, c+h*vz**2]
    ]
    return np.array(rotation_matrix)

# https://www.learnopencv.com/rotation-matrix-to-euler-angles/
def rotation_matrix_to_euler(R):
    """Convert rotation matrix (R) to euler [x, y, z] format"""
    sy = math.sqrt(R[0,0] * R[0,0] +  R[1,0] * R[1,0])

    singular = sy < 1e-6

    if  not singular :
        x = math.atan2(R[2,1] , R[2,2])
        y = math.atan2(-R[2,0], sy)
        z = math.atan2(R[1,0], R[0,0])
    else :
        x = math.atan2(-R[1,2], R[1,1])
        y = math.atan2(-R[2,0], sy)
        z = 0

    return np.array([x, y, z])


# Fast modulo exponentiation of numbers using Euler
# Rafał Lal 10/06/2021
import sys
from sympy.ntheory import isprime
from math import gcd

def euler_function(num):
    if isprime(num):
        return num - 1
    result = 1
    for i in range(2, num):
        if gcd(i, num) == 1:
            result += 1
    return result

def euler_theorem(a, n, m):
    eul = euler_function(m)
    n1 = n % eul
    n2 = pow(a, n1)
    return eul, n2 % m

def main():
    try:
        a = int(input('Base: '))
        n = int(input('Power: '))
        m = int(input('Mod: '))
        if n < 1 or m < 1 or gcd(a, m) != 1:
            raise ValueError
    except ValueError:
        print('Numbers does not fulfil requirements')
        sys.exit()

    e, r = euler_theorem(a, n, m)
    print('Euler({}) = {}'.format(m, e), "Result = {} <{}>".format(r, m), sep='\n')

if __name__ == '__main__':
    main()


from numpy import array as ary; from numpy import log as ln
from numpy import cos, sin, pi, sqrt, exp, arccos, e
tau = 2*pi
import numpy as np;
from matplotlib import pyplot as plt

def plot_complex(*lines_data, **kwargs):
    for line in lines_data:
        plt.plot(np.real(line), np.imag(line), **kwargs)
    return

def expo(base, exponent):
    mag = ln(np.absolute(base))
    arg = np.angle(base)
    x = np.real(exponent)
    y = np.imag(exponent)
    return exp(x*mag-y*arg) * exp(1j* (x*arg + y*mag))

if __name__=='__main__':
    #make a cartesian grid
    # x0 = np.arange(-0,9)
    x0 = np.arange(-pi, pi, 0.2)
    y0 = np.arange(-pi, pi, 0.2)
    x_ = 0
    y_ = 1
    z_ = x_ + y_*1j
    # z_ = exp(1j*np.linspace(0, pi))

    vert_lines = ary(np.meshgrid(x0, y0*1j)).T.sum(axis=2)
    horiz_lines = ary(np.meshgrid(y0*1j, x0)).T.sum(axis=2)
    plt.style.use('dark_background')
    plot_complex(*horiz_lines, color='C0')
    plot_complex(*vert_lines, color='C0')

    plot_complex(*( expo(horiz_lines, z_) ))
    plot_complex(*( expo(vert_lines, z_) ))
    plt.show()


from math import ceil, floor

import numpy as np
from aocd.models import Puzzle

def solve_puzzle_one(input_array):
    ids = map(lambda bp: calc_id(bp, 7), input_array)
    print(max(ids))

def calc_id(bp, length_first=7):
    first = bp[0:length_first]
    sec = bp[length_first:]
    first_upper = pow(2, len(first)) - 1
    sec_upper = pow(2, len(sec)) - 1
    row = calc_id_rec(first, 0, first_upper)
    column = calc_id_rec(sec, 0, sec_upper)
    return row * 8 + column

def calc_id_rec(id, l, u):
    if len(id) == 0:
        assert (l == u)
        return l
    update = (u - l) / 2
    if id[0] == 'F' or id[0] == 'L':
        return calc_id_rec(id[1:], l, floor(u - update))
    else:
        return calc_id_rec(id[1:], ceil(l + update), u)

def solve_puzzle_two(input_array):
    ids = map(lambda bp: calc_id(bp, 7), input_array)

    sorted_ids = np.array(np.sort(list(ids)))
    missing = np.diff(sorted_ids)
    print(sorted_ids[np.argwhere(missing > 1)[0, 0]] + 1)

def parse_input(data):
    return np.array(data.splitlines())

test_input = """
FBFBBFFRLR"""

if __name__ == '__main__':
    puzzle = Puzzle(year=2020, day=5)
    if False:
        array = parse_input(test_input)
    else:
        array = parse_input(puzzle.input_data)
    solve_puzzle_one(array)
    solve_puzzle_two(array)


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

# # 🏁 Wrap-up quiz
#
# **This quiz requires some programming to be answered.**
#
# Open the dataset `house_prices.csv` with the following command:

# In[1]:

import pandas as pd

ames_housing = pd.read_csv("../datasets/house_prices.csv", na_values="?")
target_name = "SalePrice"
data = ames_housing.drop(columns=target_name)
target = ames_housing[target_name]

# `ames_housing` is a pandas dataframe. The column "SalePrice" contains the
# target variable. Note that we instructed pandas to treat the character "?" as a
# marker for cells with missing values also known as "null" values.
#
# To simplify this exercise, we will only used the numerical features defined
# below:

# In[2]:

numerical_features = [
    "LotFrontage", "LotArea", "MasVnrArea", "BsmtFinSF1", "BsmtFinSF2",
    "BsmtUnfSF", "TotalBsmtSF", "1stFlrSF", "2ndFlrSF", "LowQualFinSF",
    "GrLivArea", "BedroomAbvGr", "KitchenAbvGr", "TotRmsAbvGrd", "Fireplaces",
    "GarageCars", "GarageArea", "WoodDeckSF", "OpenPorchSF", "EnclosedPorch",
    "3SsnPorch", "ScreenPorch", "PoolArea", "MiscVal",
]

data_numerical = data[numerical_features]

# We will compare the statistical performance of a decision tree and a linear
# regression. For this purpose, we will create two separate predictive models
# and evaluate them by 10-fold cross-validation.
#
# Thus, use `sklearn.linear_model.LinearRegression` and
# `sklearn.tree.DecisionTreeRegressor` to create the model. Use the default
# parameters for both models.
#
# **Note**: missing values should be handle with a scikit-learn
# `sklearn.impute.SimpleImputer` and the default strategy (`"mean"`). Be also
# aware that a linear model requires to scale the data. You can use a
# `sklearn.preprocessing.StandardScaler`.

# In[8]:

from sklearn.linear_model import LinearRegression
from sklearn.tree import DecisionTreeRegressor

from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.impute import SimpleImputer

from sklearn.model_selection import cross_validate

linear_model = make_pipeline(StandardScaler(), SimpleImputer(), LinearRegression())
tree_model = make_pipeline(SimpleImputer(), DecisionTreeRegressor())

linear_cv_result = cross_validate(linear_model, data_numerical, target, cv=10, return_estimator=True, scoring='r2')
print(f'Score for linear model is {linear_cv_result["test_score"].mean():0.2f} +/- {linear_cv_result["test_score"].std():0.2f}')

tree_cv_result = cross_validate(tree_model, data_numerical, target, cv=10, return_estimator=True, scoring='r2')
print(f'Score for tree model is {tree_cv_result["test_score"].mean():0.2f} +/- {tree_cv_result["test_score"].std():0.2f}')

# # Question 1
# Is the decision tree model better in terms of $R^2$ score than the linear
# regression?
#
# - a) Yes
# - b) No
#
# _Select a single answer_

# Instead of using the default parameter for decision tree regressor, we will
# optimize the depth of the tree. Using a grid-search
# (`sklearn.model_selection.GridSearchCV`) with a 10-fold cross-validation,
# answer to the questions below. Vary the `max_depth` from 1
# level up to 15 levels.

# In[10]:

tree_model.get_params()

# In[15]:

from sklearn.model_selection import GridSearchCV
import numpy as np

param_grid = {"decisiontreeregressor__max_depth": np.arange(1, 15, 1)}
tree_reg = GridSearchCV(tree_model, param_grid=param_grid, cv=10, scoring='r2')
tree_reg.fit(data_numerical, target)

# In[17]:

tree_reg.best_params_['decisiontreeregressor__max_depth']

# # Question 2
# What is the optimal tree depth for the current problem?
#
# - a) The optimal depth is ranging from 3 to 5
# - b) The optimal depth is ranging from 5 to 8
# - c) The optimal depth is ranging from 8 to 11
# - d) The optimal depth is ranging from 11 to 15
#
# _Select a single answer_
#

# In[19]:

tree_reg.best_score_

# # Question 3
# A tree with an optimal depth is performing:
#
# - a) better than a linear model
# - b) equally to a linear model
# - c) worse than a linear model
#
# _Select a single answer_

# Instead of using only the numerical dataset (which was the variable
# `data_numerical`), use the entire dataset available in the variable `data`.
#
# Create a preprocessor by dealing separately with the numerical and categorical
# columns. For the sake of simplicity, we will define the categorical columns as
# the columns with an `object` data type.
#
# **Do not optimize the `max_depth` parameter for this exercise.**

# In[39]:

from sklearn.linear_model import LinearRegression
from sklearn.tree import DecisionTreeRegressor

from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.impute import SimpleImputer

from sklearn.model_selection import cross_validate

from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import OneHotEncoder

from sklearn.compose import make_column_selector as selector

from sklearn.pipeline import Pipeline

categorical_columns_selector = selector(dtype_include=object)
categorical_columns = categorical_columns_selector(data)

numeric_transformer = Pipeline(steps=[
    ('imputer', SimpleImputer(strategy='mean')),
    ('scaler', StandardScaler())])
categorical_transformer = Pipeline(steps=[
    ('imputer', SimpleImputer(strategy="most_frequent", verbose=1)),
    ('onehotencoder', OneHotEncoder(handle_unknown = 'ignore'))])

linear_preprocessor = ColumnTransformer(transformers=[
     ("num-preprocessor", numeric_transformer, numerical_features),
    ("cat-preprocessor", categorical_transformer, categorical_columns)
])

tree_preprocessor = ColumnTransformer(transformers=[
     ("num-preprocessor", SimpleImputer(), numerical_features),
    ("cat-preprocessor", categorical_transformer, categorical_columns)
])

linear_model = make_pipeline(linear_preprocessor, LinearRegression())
linear_cv_result = cross_validate(linear_model, data, target, cv=10, return_estimator=True, scoring='r2')

print(f'Score is {linear_cv_result["test_score"].mean():0.2f} +/- {linear_cv_result["test_score"].std():0.2f}')

tree_model = make_pipeline(tree_preprocessor, DecisionTreeRegressor())
tree_cv_result = cross_validate(tree_model, data, target, cv=10, return_estimator=True, scoring='r2')
print(f'Score for tree model is {tree_cv_result["test_score"].mean():0.2f} +/- {tree_cv_result["test_score"].std():0.2f}')

# # Question 4
# Are the performance in terms of $R^2$ better by incorporating the categorical
# features in comparison with the previous tree with the optimal depth?
#
# - a) No the statistical performance are the same: ~0.7
# - b) The statistical performance is slightly better: ~0.72
# - c) The statistical performance is better: ~0.74
#
# _Select a single answer_
#

# In[ ]:

jupyter-book/trees/module 5 - wrap-up-quizz.py


import keras
print(keras.__version__)

import numpy as np

# word level one hot code

# This is our initial data; one entry per "sample"
# (in this toy example, a "sample" is just a sentence, but
# it could be an entire document).
samples = ['The cat sat on the mat.', 'The dog ate my homework.']

# First, build an index of all tokens in the data.
token_index = {}
for sample in samples:
    # We simply tokenize the samples via the `split` method.
    # in real life, we would also strip punctuation and special characters
    # from the samples.
    for word in sample.split():
        if word not in token_index:
            # Assign a unique index to each unique word
            token_index[word] = len(token_index) + 1
            # Note that we don't attribute index 0 to anything.

print("token_index: ", token_index)
# token_index:{'The': 1, 'cat': 2, 'sat': 3, 'on': 4, 'the': 5, 'mat.': 6, 'dog': 7, 'ate': 8, 'my': 9, 'homework.': 10}

# Next, we vectorize our samples.
# We will only consider the first `max_length` words in each sample.
max_length = 10

# This is where we store our results:
results = np.zeros((len(samples), max_length, max(token_index.values()) + 1))  # shape: (2, 10, 11)
for i, sample in enumerate(samples):
    for j, word in list(enumerate(sample.split()))[:max_length]:
        index = token_index.get(word)
        results[i, j, index] = 1.

print("results: ", results)  # a 0 or 1 array which shape is (2, 10, 11) 10 is row # and 11 is coloumn #

print('word level one hot code done')
print('---------------------------------------------------------------------------------------------------------------')

# character level one hot code

import string

samples = ['The cat sat on the mat.', 'The dog ate my homework.']
characters = string.printable  # All printable ASCII characters. refer to printable definition
print('characters: ', characters)
# characters:  0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~

token_index = dict(zip(characters, range(1, len(characters) + 1)))
print('token_index: ', token_index)
# token_index:  {'0': 1, '1': 2, '2': 3, '3': 4, '4': 5, '5': 6, '6': 7, '7': 8, '8': 9, '9': 10, 'a': 11, 'b': 12,
# 'c': 13, 'd': 14, 'e': 15, 'f': 16, 'g': 17, 'h': 18, 'i': 19, 'j': 20, 'k': 21, 'l': 22, 'm': 23, 'n': 24, 'o': 25,
# 'p': 26, 'q': 27, 'r': 28, 's': 29, 't': 30, 'u': 31, 'v': 32, 'w': 33, 'x': 34, 'y': 35, 'z': 36, 'A': 37, 'B': 38,
# 'C': 39, 'D': 40, 'E': 41, 'F': 42, 'G': 43, 'H': 44, 'I': 45, 'J': 46, 'K': 47, 'L': 48, 'M': 49, 'N': 50, 'O': 51,
# 'P': 52, 'Q': 53, 'R': 54, 'S': 55, 'T': 56, 'U': 57, 'V': 58, 'W': 59, 'X': 60, 'Y': 61, 'Z': 62, '!': 63, '"': 64,
# '#': 65, '$': 66, '%': 67, '&': 68, "'": 69, '(': 70, ')': 71, '*': 72, '+': 73, ',': 74, '-': 75, '.': 76, '/': 77,
# ':': 78, ';': 79, '<': 80, '=': 81, '>': 82, '?': 83, '@': 84, '[': 85, '\\': 86, ']': 87, '^': 88, '_': 89, '`': 90,
# '{': 91, '|': 92, '}': 93, '~': 94, ' ': 95, '\t': 96, '\n': 97, '\r': 98, '\x0b': 99, '\x0c': 100}

max_length = 50
results = np.zeros((len(samples), max_length, max(token_index.values()) + 1))  # shape: (2, 50, 101)
for i, sample in enumerate(samples):
    for j, character in enumerate(sample[:max_length]):
        index = token_index.get(character)
        results[i, j, index] = 1.

print('character level one hot code done')
print('---------------------------------------------------------------------------------------------------------------')

# word level one hot code with Keras

from keras.preprocessing.text import Tokenizer

samples = ['The cat sat on the mat.', 'The dog ate my homework.']

# We create a tokenizer, configured to only take
# into account the top-1000 most common words
tokenizer = Tokenizer(num_words=1000)
# This builds the word index
tokenizer.fit_on_texts(samples)

# This turns strings into lists of integer indices.
sequences = tokenizer.texts_to_sequences(samples)

# You could also directly get the one-hot binary representations.
# Note that other vectorization modes than one-hot encoding are supported!
one_hot_results = tokenizer.texts_to_matrix(samples, mode='binary')

# This is how you can recover the word index that was computed
word_index = tokenizer.word_index
print('Found %s unique tokens.' % len(word_index))  # Found 9 unique tokens.
print('word index: ', word_index)
# word index:  {'the': 1, 'cat': 2, 'sat': 3, 'on': 4, 'mat': 5, 'dog': 6, 'ate': 7, 'my': 8, 'homework': 9} no "." in!

print('word level one hot code with Keras done')
print('---------------------------------------------------------------------------------------------------------------')

# word level one hot code with a skill

samples = ['The cat sat on the mat.', 'The dog ate my homework.']

# We will store our words as vectors of size 1000.
# Note that if you have close to 1000 words (or more)
# you will start seeing many hash collisions, which
# will decrease the accuracy of this encoding method.
dimensionality = 1000
max_length = 10

results = np.zeros((len(samples), max_length, dimensionality))
for i, sample in enumerate(samples):
    for j, word in list(enumerate(sample.split()))[:max_length]:
        # Hash the word into a "random" integer index
        # that is between 0 and 1000
        index = abs(hash(word)) % dimensionality
        # hash: retuan a hash value; abs: retuan a absolute active value; % retuan a remaind value in [0, 1000)
        results[i, j, index] = 1.

print('word level one hot code with a skill done')
print('---------------------------------------------------------------------------------------------------------------')


# -*- coding: utf-8 -*-
"""
Created on Mon Mar 25 15:31:35 2019

INSTITUTO FEDERAL DE EDUCAÇÃO, CIÊNCIA E TECNOLOGIA DO PÁRA - IFPA ANANINDEUA

@author:
        Prof. Dr. Denis C. L. Costa

        Discentes:
            Heictor Alves de Oliveira Costa
            Lucas Pompeu Neves

Grupo de Pesquisa:
                 Gradiente de Modelagem Matemática e
                 Simulação Computacional - GM²SC

Assunto:
        Representação de Gráfica de Funções com duas variáveis independentes

Nome do sript: graficos_3d

Disponível em:
    https://github.com/GM2SC/DEVELOPMENT-OF-MATHEMATICAL-METHODS-IN-
    COMPUTATIONAL-ENVIRONMENT/blob/master/SINEPEM_2019/graficos_3d.py

"""
# Bibliotecas

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

# Comandos para plotar Gráficos em 3D
fig = plt.figure(1)
ax = Axes3D(fig)

# Intervalos de Análises: (x1, x2) e (y1, y2)
x1 = -5; x2 = 5
y1 = -5; y2 = 5
# Elemento de discretização: d
d = 0.25
x = np.arange(x1, x2, d)
# Valores de y:
y = np.arange(y1, y2, d)
print('')
print('=======================================')
print('Intervalos de Análises:')
print('(x1, x2), (y1, y2):', (x1, x2), (y1, y2))
print('=======================================')

# Função de duas Variáveis: z(x,y)
x, y = np.meshgrid(x, y)
z = x**2 + y**2

# Títulos do Gráfico 3D
ax.set_xlabel('Valores de x')
ax.set_ylabel('Valores de y')
ax.set_zlabel('Valores de z')
ax.set_title('Superfície de z = f(x,y)')

# Layout do Gráfico 3D:
# Opções de cores: cmap --> escolha a letra correspondente
a =  'Spectral'
b =  'seismic'
c =  'coolwarm'
d =  'PRGn'
e = 'RdYlBu'
f = 'RdGy'
g = 'RdYlGn'

ax.plot_surface(x, y, z, cmap = b)
print('')
print(' **** Gráficos gerados pelo Programa graficos_3d ****')

# Gráfico de Contornos
fig = plt.figure()
# n --> Número de linhas de contorno
n = 25
plt.contour(x, y, z, n)
plt.xlabel('Valores de x')
plt.ylabel('Valores de y')
plt.title('Curvas de Nível de z = f(x,y)')
plt.show()


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
__author__ = 'cnheider'

import math

import numpy as np
import torch

def entropy(prob):
  return -torch.sum(prob * torch.log(prob), 1)

def log_entropy(log_prob):
  return -torch.sum(torch.exp(log_prob) * log_prob, 1)

def kl_log_probs(log_prob1, log_prob2):
  return -torch.sum(torch.exp(log_prob1) * (log_prob2 - log_prob1), 1)

def kl_probs(prob1, prob2):
  return -torch.sum(prob1 * torch.log(prob2 / prob1), 1)

def to_tensor(obj, dtype=torch.float, device='cpu'):
  if not torch.is_tensor(obj):
    return torch.tensor(obj, device=device, dtype=dtype)
  else:
    return obj.type(dtype).to(device)

def pi_torch(device='cpu'):
  return to_tensor([np.math.pi], device=device)

def normal(x, mu, sigma_sq, device='cpu'):
  a = (-1 * (to_tensor(x, device=device) - mu).pow(2) / (2 * sigma_sq)).exp()
  b = 1 / (2 * sigma_sq * pi_torch(device=device).expand_as(sigma_sq)).sqrt()
  return a * b

def normal_entropy(std):
  var = std.pow(2)
  ent = 0.5 + 0.5 * torch.log(2 * var * math.pi)
  return ent.sum(1, keepdim=True)

def normal_log_density(x, mean, log_std, std):
  var = std.pow(2)
  log_density = -(x - mean).pow(2) / (2 * var) - 0.5 * math.log(2 * math.pi) - log_std
  return log_density.sum(1, keepdim=True)


import numpy as np

def __sigmoid(x, derive=False):
    if derive:
        return x * (1 - x)
    return 1 / (1 + np.exp(-x))


import matplotlib.pyplot as plt
import numpy as np
from sklearn.linear_model import LinearRegression, Ridge, Lasso
from sklearn.preprocessing import PolynomialFeatures
from sklearn.model_selection import train_test_split
from sklearn.pipeline import make_pipeline
from sklearn.utils import resample
from sklearn import preprocessing

np.random.seed(2018)

n = 40
n_boostraps = 100
maxdegree = 14

# Make data set.
x = np.linspace(-3, 3, n).reshape(-1, 1)
x = preprocessing.scale(x)
y = np.exp(-x**2) + 1.5 * np.exp(-(x-2)**2)+ np.random.normal(0, 0.1, x.shape)
error = np.zeros(maxdegree)
bias = np.zeros(maxdegree)
variance = np.zeros(maxdegree)
polydegree = np.zeros(maxdegree)
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2)

for degree in range(maxdegree):
    model = make_pipeline(PolynomialFeatures(degree=degree), LinearRegression(fit_intercept=False))
    y_pred = np.empty((y_test.shape[0], n_boostraps))
    for i in range(n_boostraps):
        x_, y_ = resample(x_train, y_train)
        y_pred[:, i] = model.fit(x_, y_).predict(x_test).ravel()

    polydegree[degree] = degree
    error[degree] = np.mean( np.mean((y_test - y_pred)**2, axis=1, keepdims=True) )
    bias[degree] = np.mean( (y_test - np.mean(y_pred, axis=1, keepdims=True))**2 )
    variance[degree] = np.mean( np.var(y_pred, axis=1, keepdims=True) )

plt.plot(polydegree, error, label='Error')
plt.plot(polydegree, bias, label='bias')
plt.plot(polydegree, variance, label='Variance')
plt.legend()
plt.show()


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

from numpy import *
from random import *
import matplotlib.pyplot as plt

'''
最小二乘法（又称最小平方法）:
    通过最小化误差的平方和寻找数据的最佳函数匹配。
    利用最小二乘法可以简便地求得未知的数据，并使得这些求得的数据与实际数据之间误差的平方和为最小。
    最小二乘法还可用于曲线拟合。其他一些优化问题也可通过最小化能量或最大化熵用最小二乘法来表达。

matplotlib： python 的2D 绘图库
'''

class LeastSquares:
    def __init__(self):
        pass

    '''
    一元线性回归
    x**y : x 的 y 次方
    sum(list) 表示 list 中算素相加的和
    // 表示整数除法
    / 表示浮点数除法
    '''
    def OneLeastSquares(self):
        x = [1, 2, 3, 5, 6, 12, 11, 13]
        y = [4, 5, 8, 13, 12, 23, 20, 22]
        # 求平均数（list所有元素的和/元素的个数）
        average_x = float(sum(x)) // len(x)
        average_y = float(sum(y)) / len(y)
        # 求残差
        x_sub = list(map((lambda x: x - average_x), x))
        y_sub = list(map((lambda x: x - average_y), y))
        # 残差平方
        x_sub_pow2 = list(map((lambda x: x ** 2), x_sub))
        y_sub_pow2 = list(map((lambda x: x ** 2), y_sub))
        # 残差成积
        x_y = list(map((lambda x, y: x * y), x_sub, y_sub))

        # 获取 最小残差平方和
        min_sub_pow2 = minimum(sum(x_sub_pow2), sum(y_sub_pow2))

        # 残差成积和/x方向的残差平方和
        a = float(sum(x_y)) / min_sub_pow2
        b = average_y - a * average_x
        plt.xlabel('X')
        plt.ylabel('Y')
        plt.plot(x, y, '*')
        plt.plot([0, 15], [0 * a + b, 15 * a + b])
        plt.grid()
        plt.show()

    def MoreLeastSquares(self):
        x, y, xr, yr = self.Data()
        X, Y = self.MAT(x, y, 9)
        XT = X.transpose()
        B = dot(dot(linalg.inv(dot(XT, X)), XT), Y)
        myY = dot(X, B)
        self.fig(x, myY, xr, yr)

    def Data(self):
        x = arange(-1, 1, 0.02)
        y = ((x * x - 1) ** 2 + 2) * (sin(x * 3) + 0.7 * cos(x * 1.2))
        xr = []
        yr = []
        i = 0
        for xx in x:
            yy = y[i]
            d = float(randint(80, 120)) / 100
            i += 1
            xr.append(xx * d)
            yr.append(yy * d)
        return x, y, xr, yr

    def MAT(self, x, y, order):
        X = []
        for i in range(order + 1):
            X.append(x ** i)
        X = mat(X).T
        Y = array(y).reshape((len(y), 1))
        return X, Y

    def fig(self, x1, y1, x2, y2):
        plt.xlabel('X')
        plt.ylabel('Y')
        plt.plot(x1, y1, color='g', linestyle='-', marker='')
        plt.plot(x2, y2, color='m', linestyle='', marker='.')
        plt.grid()
        plt.show()

LeastSquares().OneLeastSquares()
LeastSquares().MoreLeastSquares()


from RandomConcentration import fake_data
import numpy as np
import numpy.linalg as la

def generate_A(r, t):
    m = len(r)
    n = len(t)
    A = np.zeros((n, m))
    for j in range(n):
        for i in range(m):
            A[j][i] = np.exp(-1*r[i]*t[j])
    return A

def Cholesky(A, b):
    b = np.transpose(A)@b
    A = np.transpose(A)@A
    L = la.cholesky(A)
    y = la.lstsq(L, b, rcond=None)[0]
    x = la.lstsq(np.transpose(L), y, rcond=None)[0]
    return x

def QR(A, b):
    Q, R = la.qr(A)
    y = la.lstsq(Q, b, rcond=None)[0]
    x = la.lstsq(R, y, rcond=None)[0]
    return x

def SVD(A, b):
    U, S, Vh = la.svd(A)
    y = la.lstsq(U, b, rcond=None)[0]
    x = la.lstsq(np.diag(S)@Vh, y, rcond=None)[0]
    cond = max(S)/min(S)
    return x, cond

#easy problem
m = 5
n = 5
A_seed = 3
A_mu = 20.
A_sig = 1
r_seed = 19
r_mu = 20.
r_sig = 1
xi_seed = 2
xi_mu = 0
xi_sig = 0
r, t, F = fake_data(m, n, A_seed, A_mu, A_sig, r_seed, r_mu, r_sig, xi_seed, \
    xi_mu, xi_sig)
A = generate_A(r, t)
x_cho = Cholesky(A, F)
x_qr = QR(A, F)
x_svd, cond = SVD(A, F)

print("\nRMS differences between resulting solution vectors\n")
dim_info = "Dimension: m = {m:3d}, n = {n:3d}\n"
dim_info = dim_info.format(m = m, n = n)
print(dim_info)
A_info = "A:  seed = {A_seed:3d}, entry mean = {A_mu:8.1f}, sd = {A_sig:8.2f}"
A_info = A_info.format( A_seed = A_seed, A_mu = A_mu, A_sig = A_sig)
print(A_info)
r_info = "r:  seed = {r_seed:3d}, entry mean = {r_mu:8.1f}, sd = {r_sig:8.2f}"
r_info = r_info.format( r_seed = r_seed, r_mu = r_mu, r_sig = r_sig)
print(r_info)
xi_info = "xi: seed = {xi_seed:3d}, entry mean = {xi_mu:8.1f}, sd = {xi_sig:8.2f}\n"
xi_info = xi_info.format( xi_seed = xi_seed, xi_mu = xi_mu, xi_sig = xi_sig)
print(xi_info)
cq_info = "Cholesky vs. QR: {cq:14.6e}"
cs_info = "Cholesky vs SVD: {cs:14.6e}, condition number = {cond:14.6e}"
qs_info = "QR vs SVD:       {qs:14.6e}"
cq_info = cq_info.format( cq = la.norm(x_cho-x_qr))
cs_info = cs_info.format( cs = la.norm(x_cho-x_svd), cond = cond)
qs_info = qs_info.format( qs = la.norm(x_qr-x_svd))
print(cq_info)
print(cs_info)
print(qs_info)

Scientific Computing Projects (Code Parts)/3/Problem 2/LeastSquare.py


def verify_1a(answer):

    import sympy

    S = sympy.Symbol('S', positive=True)
    return answer == 2*S/9

def solve_1b():

    import sympy

    m = sympy.Symbol('m', positive=True) # Particle mass
    h = sympy.Symbol('h', positive=True) # Planck constant
    E = sympy.Symbol('E', positive=True) # Particle energy
    V_0 = sympy.Symbol('V_0', positive=True) # Potential step
    R = sympy.Symbol('R') # Reflection coefficient
    T = sympy.Symbol('T') # Transmission coefficient
    x = sympy.Symbol('x',real=True) # Position
    left_wave = sympy.exp(sympy.I*x*sympy.sqrt(2*m*E)/h) + R*sympy.exp(-sympy.I*x*sympy.sqrt(2*m*E)/h)
    right_wave = T*sympy.exp(sympy.I*x*sympy.sqrt(2*m*(E-V_0))/h)

    continuity = sympy.Eq(left_wave.subs(x,0), right_wave.subs(x,0))
    differentiability = sympy.Eq(left_wave.diff(x).subs(x,0), right_wave.diff(x).subs(x,0))
    sol = sympy.solve([continuity,differentiability],[R,T])
    return sol

def verify_1bI(answer):

    import sympy

    sol = solve_1b()
    return sol[sympy.Symbol('R')]==answer

def verify_1bII(answer):

    import sympy

    sol = solve_1b()
    return sol[sympy.Symbol('T')]==answer

def verify_2a(answer):

    import sympy

    G = sympy.Symbol('G', positive=True) # Gravitation constant
    M = sympy.Symbol('M', positive=True) # Mass
    t = sympy.Symbol('t', positive=True) # Time
    b = sympy.Symbol('b', positive=True) # Impact parameter
    v = sympy.Symbol('v', positive=True) # Particle velocity

    acceleration = G*M*b/(v**2*t**2+b**2)**sympy.Rational(3,2)

    solution = sympy.integrate(acceleration,(t,-sympy.oo,sympy.oo))

    return solution == answer

def verify_3a(answer):

    import sympy

    s = sympy.Symbol('s', positive=True) # Separation
    Q = sympy.Symbol('Q', positive=True) # Charge
    r = sympy.Symbol('r', positive=True) # Radius
    q = sympy.Symbol('theta', positive=True) # Angle

    potential = 2*Q/r-Q/sympy.sqrt(r**2+s**2+2*s*r*sympy.cos(q))-Q/sympy.sqrt(r**2+s**2-2*s*r*sympy.cos(q))

    temp = sympy.series(potential,s,0,3).removeO().simplify()

    return (temp/answer).simplify() == 1

def verify_4a(answer):

    return answer==1

def verify_5a(answer):

    import sympy

    x = sympy.Symbol('x', real=True)
    k = sympy.Symbol('k', real=True)
    func = sympy.exp(-x**2)

    solution = sympy.fourier_transform(func,x,k)
    return answer == solution

def verify_6a(answer):

    import sympy

    x = sympy.Function('x', real=True)
    t = sympy.Symbol('t', real=True)

    eqn = sympy.Eq(x(t).diff(t,2), -x(t)+sympy.sin(2*t))
    init_cond = {x(0):0,
                x(t).diff(t).subs(t,0):0}
    sol = sympy.dsolve(eqn,x(t),ics=init_cond)
    if not type(sol)==type(answer):
        print('wrong type')
        return False
    return sol == answer


"""
Sierpinsky triangle using chaos game
Rule:
    draw vertices of eq.triangle
    make a randon point inside triangle
    take a random vertex
    plot midpoint
    take that midpoint as next random point
    repeat
"""

import numpy as np
import matplotlib.pyplot as plt

N = 20000
x = np.zeros(N)
y = np.zeros(N)
c = np.zeros(N, dtype=np.object)

V = ((0, 0), (1, 0), (0.5, np.sqrt(3)/2))
p = (0.5, 0.5)

x[:3] = [j[0] for j in V]
y[:3] = [j[1] for j in V]
c[:3] = ["#FF7029","#3AFF21", "#B450C9"]

for i in range(3, N):
    n = np.random.choice([0, 1, 2])
    v = V[n]
    xm = (p[0] + v[0])/2.
    ym = (p[1] + v[1])/2.
    x[i] = xm
    y[i] = ym
    p = (xm, ym)
    c[i] = c[n]

# print(x)
# print(y)
# print(c)
fig = plt.figure(figsize = (12, 12))
plt.axis("off")
plt.scatter(x, y, c=c, s=0.5)
plt.show()


import math
import sympy
import collections
import time
from operator import mul
from functools import reduce
from itertools import product

# ordered_partitions...
def partitions_with_count(k):
    """
    return all possible partitions of a set with n elements grouped by the number of elements in each partition

    for example, paritions_with_count(3) returns {(1, 2): 3, (3,): 1, (1, 1, 1): 1}
    (1, 2)      -> [1],[2,3];  [2],[1,3];  [3],[1,2]    -> total of 3 ways
    (3,)        -> [1,2,3]                              -> total of 1 way
    (1, 1, 1)   -> [1],[2],[3]                          -> total of 1 way
    """
    if len(k) == 1 and k[0] == 1:
        return {((1,),): 1}  # the only way to partition set with one element

    unordered_len = []
    for i in sympy.utilities.iterables.multiset_partitions(
            [(group, j) for group, tot in enumerate(k) for j in range(tot)]):
        count_len = []
        for j in i:
            # print(j)
            ans = [0] * len(k)
            for kk in j:
                ans[kk[0]] += 1
            count_len.append(tuple(ans))
        unordered_len.append(tuple(sorted(count_len)))
    # all_partitions = sympy.utilities.iterables.multiset_partitions(range(k[0]))
    # all_partitions = sympy.utilities.iterables.multiset_partitions([(group, j) for group, tot in enumerate(k) for j in range(tot)])
    # unordered_len = [tuple(sorted([len(j) for j in i])) for i in all_partitions]
    return collections.Counter(unordered_len)

def integer_partitions(target, nb_ele):
    """
    return all possible ways to sum to target using nb_ele, allowing 0 to be one of the element

    for example, integer_partitions(4, 2) returns
    ([0,4], [4,0], [1,3], [3,1], [2,2])
    """
    if target == 0:
        return [[0] * nb_ele]

    ans = []
    for i in range(nb_ele):
        for part in sympy.utilities.iterables.ordered_partitions(target, m=i+1):
            arr = [0] * (nb_ele - (i + 1)) + part
            for j in sympy.utilities.iterables.multiset_permutations(arr):
                ans.append(j)
    return ans

def fdb_1d(k):
    """
    faa di bruno formula for 1 dimension

    for example, fdb_1d(k) return a list of size m x 3 such that
    d^k f(g(x)) = sum_{i=0}^{m-1} ans[i].coeff x f[ans[i].lamb]
                    x prod_{j=0}^{ans[i].s - 1} g[ans[i].l[j]]^[ans[i].k[j]],
    where f[n] means differentiate f n times
    ans[i].coeff is the index 0 of ans[i]
    ans[i].lamb is the index 1 of ans[i]
    ans[i].l is the key of the dictionary at index 2 of ans[i]
    ans[i].k is the value of the dictionary at index 2 of ans[i]
    ans[i].s is the size of the dictionary at index 2 of ans[i]
    """
    fdb = collections.namedtuple('fdb', 'coeff lamb l_and_k')
    return [fdb(count, len(par), collections.Counter(par))
            for par, count in partitions_with_count(k).items()]

def fdb_nd(n, ks):
    """
    the main function, multivariate faa di bruno formula for
    d^k1/dx1 d^k2/dx2 ... d^kd/dxd f(g1(x), g2(x), ..., gn(x))

    this implementation is derived from the R package kStatistics::MFB
    """
    fdb = collections.namedtuple('fdb', 'coeff lamb l_and_k')
    ans = []

    for par in product(*[integer_partitions(k, n) for k in ks]):
        # transpose par without numpy
        par = list(zip(*par))
        # k! / (par0! par1! par2! ...)
        p = reduce(mul, [math.factorial(ele) for ele in ks]) // reduce(mul, [math.factorial(ele) for group in par for ele in group])
        for cartesian in product(*[fdb_1d(ele) for ele in par]):
            coeff, lamb, l_and_k = p, [], {}
            for idx, ele in enumerate(cartesian):
                coeff *= ele.coeff
                lamb.append(ele.lamb)
                for l, k_arr in ele.l_and_k.items():
                    if l not in l_and_k:
                        # if the dictionary does not have the key of l, initialize one using zero list
                        l_and_k[l] = [0] * len(cartesian)
                    l_and_k[l][idx] = k_arr
            ans.append(fdb(coeff, tuple(lamb), l_and_k))
    return ans

if __name__ == "__main__":
    print(fdb_nd(2, (0, 0, 0)))
    # print(fdb_nd(3, (1, 2)))
    # print(len(fdb_nd(2, (1, 2))))
    # print(fdb_1d([1]))
    # print(fdb_1d(2))
    # print(fdb_1d([1, 2]))
    # print(list(integer_partitions(4, 2)))
    # print(partitions_with_count([1, 2]))
    # start = time.time()
    # print({k: fdb_nd(5, k) for k in range(1, 10)})
    # for k in range(1, 10):
    #     # print(fdb_nd(1, k))
    #     print(len(fdb_nd(1, k)))
    # print(f"Time taken: {time.time() - start} seconds.")
    # # print(len(fdb_nd(2,5)))
    # for i in integer_partitions(2, 3):
    #     print(i)
    # print(list(integer_partitions(5, 6)))
    # print(partitions_with_count(5))


import numpy as np
from datetime import date
import sys
import matplotlib.pyplot as plt

salary = np.loadtxt("MLB2008.csv", delimiter=',', usecols=(1,), skiprows=1, unpack=True)
triples = np.arange(0, len(salary), 3)
print "Triples", triples[:10], "..."

signs = np.ones(len(salary))
print "Signs", signs[:10], "..."

signs[triples] = -1
print "Signs", signs[:10], "..."

ma_log = np.ma.log(salary * signs)
print "Masked logs", ma_log[:10], "..."

dev = salary.std()
avg = salary.mean()
inside = np.ma.masked_outside(salary, avg - dev, avg + dev)
print "Inside", inside[:10], "..."

plt.subplot(311)
plt.title("Original")
plt.plot(salary)

plt.subplot(312)
plt.title("Log Masked")
plt.plot(np.exp(ma_log))

plt.subplot(313)
plt.title("Not Extreme")
plt.plot(inside)

plt.show()


import math

__author__ = 'paoolo'

import mpmath

from nsh_app.tools import function

def linear(a=1.0, b=0.0):
    """
    Return linear activation function.

    f(x) = a * x + b

    Keyword arguments:
    a -- linear factor (default 1.0)
    b -- linear shift (default 0.0)
    """
    return function.Function(lambda x: a * x + b,
                             'activation.linear',
                             'Linear activation function')

def linear_cut():
    """
    Return partially linear activation function.

    f(x) = -1.0, x \in (-inf, -1.0)
    f(x) =    x, x \in [-1.0, +1.0)
    f(x) =  1.0, x \in [+1.0, +inf)

    """
    return function.Function(lambda x: -1.0 if x < -1.0 else (1.0 if x > 1.0 else x),
                             'activation.linear_cut',
                             'Partially linear activation function')

def threshold_unipolar(a=0.0):
    """
    Return threshold unipolar activation function.

    f(x) = 0.0, x \in (-inf, a)
    f(x) = 1.0, x \in [a, +inf)

    Keyword arguments:
    a -- threshold value (default 0.0)
    """
    return function.Function(lambda x: 0.0 if x < a else 1.0,
                             'activation.threshold_unipolar',
                             'Threshold unipolar activation function')

def threshold_bipolar(a=0.0):
    """
    Return threshold bipolar activation function.

    f(x) = -1.0, x \in (-inf, a)
    f(x) = +1.0, x \in [a, +inf)

    Keyword arguments:
    a -- threshold value (default 0.0)
    """
    return function.Function(lambda x: -1.0 if x < a else 1.0,
                             'activation.threshold_bipolar',
                             'Threshold bipolar activation function')

def sigmoid_unipolar(beta=1.0):
    """
    Return sigmoid unipolar activation function.

    f(x) = 1.0 / (1.0 + exp(-beta * x) )

    Keyword arguments:
    beta -- epsilon factor value, mostly in range (0, 1] (default 1.0)
    """
    return function.Function(lambda x: 1.0 / (1.0 + mpmath.exp(-beta * x)),
                             'activation.sigmoid_unipolar',
                             'Sigmoid unipolar activation function')

def sigmoid_bipolar(beta=1.0):
    """
    Return sigmoid bipolar activation function.

    f(x) = (1.0 - exp(-beta * x)) / (1.0 + exp(-beta * x))

    Keyword arguments:
    beta -- epsilon factor value, mostly in range (0, 1] (default 1.0)
    """

    def f(x):
        val = mpmath.exp(-beta * x)
        return (1.0 - val) / (1.0 + val)

    return function.Function(f,
                             'activation.sigmoid_bipolar',
                             'Sigmoid bipolar activation function')

def gauss(a=1.0, b=1.0, c=1.0):
    """
    Return Gauss activation function. Arguments must be greater than zero.

    f(x) = a * Epsilon - ((x-b)^2 / (2.0 * c^2))

    Keyword arguments:
    a -- Euler linear factor
    b -- linear shift
    c -- divided part
    """
    div = 2.0 * (c ** 2.0)
    return function.Function(lambda x: a * mpmath.e - (((x - b) ** 2) / div),
                             'activation.gauss',
                             'Gauss activation function')

def tanh():
    """
    Return tanh activation function.

    f(x) = tanh(x)
    """
    return function.Function(lambda x: math.tanh(x),
                             'activation.tanh',
                             'Tanh activation function')


__author__ = 'Dmitry Patashov'

import myFunctions as mf
import numpy as np
import cv2
from matplotlib import pyplot as plt
import logicFunctions as lf

img1 = cv2.imread('img1.jpg')
img3 = cv2.imread(('BlurryImage1.jpg'))

# Assignment 1:

GaussMask = 1.0/273 * np.array([[1, 4, 7, 4, 1],
                                [4, 16, 26, 16, 4],
                                [7, 26, 41, 26, 7],
                                [4, 16, 26, 16, 4],
                                [1, 4, 7, 4, 1]])

LaplacianMask = np.array([[0, -1, 0],
                          [-1, 4, -1],
                          [0, -1, 0]])

GFmat = mf.myMasking(lf.myExtendedPadding(img1.copy()), GaussMask)
LFmat = mf.myMasking(lf.myExtendedPadding(img1.copy()), LaplacianMask)

GFmat2 = GFmat - np.min(GFmat)
GFimg = np.uint8(np.round(GFmat2 * 255 / np.max(GFmat2)))

LFmat2 = np.abs(LFmat)
LFmat2 = LFmat2 - np.min(LFmat2)
LFimg = np.uint8(np.round(LFmat2 * 255 / np.max(LFmat2)))

plt.figure()
plt.subplot(221)
plt.axis('off')
plt.title('Original image')
plt.imshow(img1[:,:,::-1])

plt.subplot(222)
plt.axis('off')
plt.title('Gaussian filtered image')
plt.imshow(GFimg[:,:,::-1])

plt.subplot(223)
plt.axis('off')
plt.title('Laplacian filtered image')
plt.imshow(LFimg[:,:,::-1])

plt.subplot(224)
plt.axis('off')
plt.title('Laplacian filtered image')
plt.imshow(np.max(LFimg, axis=2), cmap='gray')

plt.show()

# Assignment 2:

myMask = np.array([[-1, -1, -1],
                   [-1, 10, -1],
                   [-1, -1, -1]])

Mimg = np.uint8(np.round(np.abs(mf.myMasking(lf.myExtendedPadding(img3.copy()), myMask))))

plt.figure()
plt.subplot(121)
plt.axis('off')
plt.title('Original image')
plt.imshow(img3[:,:,::-1])

plt.subplot(122)
plt.axis('off')
plt.title('Masked image')
plt.imshow(Mimg[:,:,::-1])

plt.show()

# Assignment 3:

img3g = cv2.cvtColor(img3, cv2.COLOR_BGR2GRAY)
Mimgg = cv2.cvtColor(Mimg, cv2.COLOR_BGR2GRAY)

hist1 = mf.myHistPlotUint8(img3g)
hist2 = mf.myHistPlotUint8(Mimgg)

plt.figure()
plt.subplot(121)
plt.title('Original image')
plt.bar(range(256), hist1)

plt.subplot(122)
plt.title('Masked image')
plt.bar(range(256), hist2)

plt.figure()
plt.subplot(121)
plt.title('Original image')
plt.bar(range(256), hist1)
plt.ylim((0, np.max(hist1) / 20))

plt.subplot(122)
plt.title('Masked image')
plt.bar(range(256), hist2)
plt.ylim((0, np.max(hist2) / 20))

plt.show()


from sympy import *
import math

def secant_method(f, x0, x1, eps=0, eta=0, max_steps=20, verbose=False):
    """两点弦截法（割线法）

    Args:
        f: function, 迭代函数
        x0, x1: float, 初值
        eps: float, 根的容许误差, default 0.
        eta: float, abs(f(x)) 的容许误差, default 0.

        max_steps: int, 最大迭代次数, default 20.
        verbose: bool, 打印出每一步的值, default False.

    Returns:
        x_final: float, 最终的近似根 x
    """
    for i in range(max_steps):
        if verbose:
            print(i, x1)

        x2 = x1 - f(x1) * (x1 - x0) / (f(x1) - f(x0))
        x0, x1 = x1, x2

        if abs(x1 - x0) <= eps or abs(f(x1)) <= eta:
            break

    return x1


import math
import numpy as np
from Point import R2_Point
import copy
from Utils import *
# 0.046
#valTol = 0.76#0.0015#0.25#0.073
percentualTol = 0.1#0.081#0.05#0.012
# 0.03512794452
def simpleRatio(A, B, C):
	AC = A.euclideanDistance(C)
	BC = B.euclideanDistance(C)
	return AC/BC

def crossRatio(A, B, C, D):
	AC = A.euclideanDistance(C)
	BC = B.euclideanDistance(C)
	AD = A.euclideanDistance(D)
	BD = B.euclideanDistance(D)

	if BC == 0 or BD == 0 or AD == 0:
		# print("cross ratio value = 0")
		# print("points: ", [A, B, C, D])
		return 0

	# if (AC/BC)*(BD/AD) > 10:
	# 	print("cross ratio value = ", (AC/BC)*(BD/AD))
	# 	print("points: ", [A, B, C, D])

	return (AC/BC)*(BD/AD)

def det3(P1, P2, P3):
	(x1, y1, z1) = unpackPoint(P1)
	(x2, y2, z2) = unpackPoint(P2)
	(x3, y3, z3) = unpackPoint(P3)

	return x1*y2*z3 + x3*y1*z2 + x2*y3*z1 - (x3*y2*z1 + x2*y1*z3 + x1*y3*z2)

def crossRatio5(A1, B1, A2, B2, O):
	det_A1_A2_O = det3(A1, A2, O)
	det_A1_B2_B1 = det3(A1, B2, B1)

	if det_A1_A2_O == 0 or det_A1_B2_B1 == 0:
		return 0

	cp1 = det3(A1, A2, B1)*det3(A1, B2, O)/(det_A1_A2_O*det_A1_B2_B1)
	#cp2 = det3(A2, A1, B1)*det3(A2, O, B2)/(det3(A2, A1, B2)*det3(A2, O, B1))
	#O = P2_Point(0, 0, 1)

	# print(det3(A1, A2, O))
	# print(det3(A1, A2, B2))
	# print(det3(A2, B1, O))
	# print(det3(A2, B1, B2))

	#cp1 = (det3(A1, A2, O)/det3(A1, A2, B2))/(det3(A2, B1, O)/det3(A2, B1, B2))
	return (cp1)#, cp2)

def fiveCrossRatio(P1, P2, P3, P4, P5):
	det124 = det3(P1, P2, P4)
	det135 = det3(P1, P3, P5)
	deno = det124*det135
	if deno == 0:
		return 0

	return det3(P1, P2, P3)*det3(P1, P4, P5)/deno

def suitable5CR(P1, P2, P3, P4, P5):
	q = fiveCrossRatio(P1, P2, P3, P4, P5)
	return 2*q/(q*q + 1)

def invariant5CrossRatio(P1, P2, P3, P4, P5):
	r = suitable5CR(P1, P2, P3, P4, P5)*suitable5CR(P1, P2, P3, P5, P4)*suitable5CR(P1, P2, P4, P5, P3)
	return r

def crossRatioFilter(points=[]):
	crossRatioValues = []
	calcCrossRatioTolerances = []
	nPoints = len(points)
	if nPoints >= 4:
		nSlideComb = nPoints - 2 #3
		for i in range(1, nSlideComb):
			#crossRatioValues.append(crossRatio(points[i], points[i+1], points[i+2], points[i+3]))
			crossRatioValues.append(crossRatio(points[0], points[i], points[i+1], points[-1]))
			#calcCrossRatioTolerances.append(calcCrossRatioTolerance(points[i], points[i+1], points[i+2], points[i+3]))

	else:
		return [0]
	return 	crossRatioValues#, calcCrossRatioTolerances)

def crossRatioFilter5(points=[], junctionPoint=None):
	crossRatioValues = []
	O = junctionPoint
	calcCrossRatioTolerances = []
	nPoints = len(points)
	if nPoints >= 4:
		nSlideComb = nPoints - 3
		for i in range(0, nSlideComb):
			crossRatioValues.append(crossRatio5(points[i], points[i+1], points[i+2], points[i+3], O))
			#calcCrossRatioTolerances.append(calcCrossRatioTolerance(points[i], points[i+1], points[i+2], points[i+3]))

	else:
		return ([0],[0])
	return 	crossRatioValues#, calcCrossRatioTolerances)

def invariant5CrossRatioFilter(points, vertice=None):
	crossRatioValues = []
	calcCrossRatioTolerances = []
	nPoints = len(points)

	factor = 0
	if vertice != None:
		factor = 1

	if nPoints >= 5 - factor:
		nSlideComb = nPoints - (4 - factor)
		for i in range(0, nSlideComb):

			if vertice != None:
				p0 = vertice
			else:
				p0 = points[i]

			crossRatioValues.append(crossRatio5(p0, points[i+1-factor], points[i+2-factor], points[i+3-factor], points[i+4-factor]))
	return crossRatioValues

def calcCrossRatioTolerance(p1, p2, p3, p4):
	# d12 = p1.euclideanDistance(p2)
	# d23 = p2.euclideanDistance(p3)
	# d34 = p3.euclideanDistance(p4)

	# d13 = d12 + d23
	# d24 = d23 + d34
	# d14 = d12 + d24

	# tol = (d13**2)*(d34**2)/((d14**2)*(d23**4)) + (d12**2)*(d13**2)/((d14**4)*(d23**2)) + (d12**2)*(d24**2)/((d14**2)*(d23**4)) + (d24**2)*(d34**2)/((d14**4)*(d23**2))

	# d14Pow2 = d14*d14
	# tol = 1/d14Pow2

	return valTol#math.sqrt(tol)

def calcDistanceTolerance(crossRatioVector):
	tol = percentualTol
	#print("crossRatioVector: ", crossRatioVector)
	seq = crossRatioVector
	return sum([r*tol for r in seq]) #math.sqrt(

def isEqualValues(val1, val2, valTol_):
	return (val2 - valTol_) <= val1 <= (val2 + valTol_)

# def isEqualVectors(crossValues1, crossValues2, tol, vectorTolerances):
# 	if len(crossValues1) == len(crossValues2):
# 		for i in range(0, len(crossValues1)):
# 			val1 = crossValues1[i]
# 			val2 = crossValues2[i]
# 			valTol_ = vectorTolerances[i]
# 			if not isEqualValues(val1, val2, valTol_):
# 				return False
# 		return True
# 	else:
# 		return False

def calcDistanceVector(vector1, vector2):
	lenVector = len(vector1)
	distance = 1000 # INF
	if lenVector == len(vector2):
		distance = 0
		for i in range(0, len(vector1)):
			val1 = vector1[i]
			val2 = vector2[i]
			diffVal = val2 - val1
			diffVal = diffVal*diffVal
			distance += diffVal
		distance = math.sqrt(distance)
	return distance

def compareCellPerCell(vector1, vector2, cell_tol):
	matchingCounter = 0
	lenVector = len(vector1)
	distance = 1000 # INF
	if lenVector == len(vector2):
		for i in range(0, len(vector1)):
			val1 = vector1[i]
			val2 = vector2[i]
			diffVal = abs(val2 - val1)
			if cell_tol*max(val1, val2) >= diffVal:
				matchingCounter += 1

	percentMatching = 0
	if lenVector > 0:
		percentMatching = matchingCounter/lenVector

	return percentMatching

def isEqualVectors(crossValues1, crossValues2, distanceTol):
	if len(crossValues1) == len(crossValues2):
		# for (val1, val2) in zip(crossValues1, crossValues2):
		# 	if not(abs(val2 - val1) <= val1*percentualTol):
		# 		return False
		# return True

		distance = calcDistanceVector(crossValues1, crossValues2)
		#if sumTol >= 2:
		#	print("size = ", len(crossValues1))
		#	print("distance = ", distance)
		#	print("sumTol = ", sumTol)
		#	print("sumTol*valTol = ", sumTol*valTol)
		#lenVector = len(crossValues1)
		#vectorTol = lenVector*valTol#sumTol#*valTol#lenVector*valTol
		# print("distance  = ", distance)
		# print("distanceTol = ", distanceTol)
		return (distance <= distanceTol)
	else:
		return False

'''
	lenVector = len(crossValues1)
	if lenVector == len(crossValues2):
		distance = 0
		for i in range(0, len(crossValues1)):
			val1 = crossValues1[i]
			val2 = crossValues2[i]
			diffVal = val2 - val1
			diffVal = diffVal*diffVal
			distance += diffVal
		distance = math.sqrt(distance)
		vectorTol = lenVector*valTol
		return (- vectorTol <= distance <= vectorTol)
'''

def compareCrossRatiosVectors(vector1, vector2, distanceTol):
	# print("vector1 = ", vector1)
	# print("vector2 = ", vector2)
	#sumTol = math.sqrt(sum([t*t for t in vectorTolerances])) #sum(tolerances2)
	if isEqualVectors(vector1, vector2, distanceTol):
		#print("compareCrossRatiosVectors: true,true")
		return (True, True)
	else:
		vector2_ = copy.deepcopy(vector2)
		vector2_.reverse()
		#print("compareCrossRatiosVectors: ", isEqualVectors(vector1, vector2_, sumTol))
		return (isEqualVectors(vector1, vector2_, distanceTol), False)

"""
A = R2_Point(0, 0)
B = R2_Point(0, 0.95)
C = R2_Point(0, 0.95+1.75)
D = R2_Point(0, 0.95+1.75+3.6)

E = R2_Point(0, 0.95+1.75+3.6 + 2.0)
F = R2_Point(0, 0.95+1.75+3.6 + 4.0)
G = R2_Point(0, 0.95+1.75+3.6 + 7.0)
H = R2_Point(0, 0.95+1.75+3.6 + 9.0)

edgePoints1 = [A, B, C, D, E, F, G, H]
edgePoints2 = [A, B, C, D, E, F, G, H]
edgePoints2.reverse()

crossRV1 = crossRatioFilter(edgePoints1)
crossRV2 = crossRatioFilter(edgePoints2)

print("cross ratio values1 = ", crossRV1)
print("cross ratio values2 = ", crossRV2)

print("compareCrossRatiosVectors = ", compareCrossRatiosVectors(crossRV1, crossRV2))
"""

# cr5vectorTemplate = [0.8993799740727911, 0.06552501293135299, 0.007481991191622515, 0.7269387781499284, 0.0034725190336924033, 0.06337601484562531, 0.9053433484125969]
# cr5vectorTest = [0.9539378247574579, 0.024929637360532646, 0.016669482399608818, 0.727639016927337, 0.0012661011136918786, 0.5976631136144654, 0.35658122903519274]

# cell_tol = 0.5
# print("compareCellPerCell: ", compareCellPerCell(cr5vectorTemplate, cr5vectorTest, cell_tol))


"""
  Name     : c15_01_vol_IBM.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 numpy as np
from matplotlib.finance import quotes_historical_yahoo_ochl as getData
#
ticker='IBM'
begdate=(2009,1,1)
enddate=(2013,12,31)
p =getData(ticker, begdate, enddate,asobject=True, adjusted=True)
ret = p.aclose[1:]/p.aclose[:-1]-1
std_annual=np.std(ret)*np.sqrt(252)
print('volatility (std)=',round(std_annual,4))


#!/usr/bin/env python

## make imports
import sys
import numpy as np
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt
import scipy.stats as stats

class TwoComponentGaussianEM():

    def __init__(self, y, numIters, numRuns,verbose=False):
        self.y = y
        self.verbose = verbose
        self.maxLike, self.bestEst = self.run_em_algorithm(numIters, numRuns)

    ### make definations for initial guessing, expectation, and maximization
    def get_init_guesses(self,y):
        ## make intial guesses for the parameters (mu1, sig1, mu2, sig2 and pi)
        n    = len(self.y)
        mu1  = y[np.random.randint(0,n)]
        mu2  = y[np.random.randint(0,n)]
        sig1 = np.random.uniform(0.5,1.5) #y.var() or 0.5,3.0
        sig2 = np.random.uniform(0.5,1.5) #y.var() or 0.5,3.0
        pi   = 0.5

        return {'n':n, 'mu1':mu1, 'mu2':mu2, 'sig1':sig1, 'sig2':sig2, 'pi':pi}

    def perform_expectation(self, y, parms):
        gammaHat = np.zeros((parms['n']),'float')

        for i in range(parms['n']):
            phiTheta1 = stats.norm.pdf(y[i],loc=parms['mu1'],scale=np.sqrt(parms['sig1']))
            phiTheta2 = stats.norm.pdf(y[i],loc=parms['mu2'],scale=np.sqrt(parms['sig2']))
            numer = parms['pi'] * phiTheta2
            denom = ((1.0 - parms['pi']) * phiTheta1) + (parms['pi'] * phiTheta2)
            gammaHat[i] = numer / denom

        return gammaHat

    def perform_maximization(self,y,parms,gammaHat):
        ## use weighted maximum likelihood fits to get updated parameter estimates
        numerMuHat1 = 0
        denomHat1 = 0
        numerSigHat1 = 0
        numerMuHat2 = 0
        denomHat2 = 0
        numerSigHat2 = 0
        piHat = 0

        ## get numerators and denomanators for updating of parameter estimates
        for i in range(parms['n']):
            numerMuHat1 = numerMuHat1 + ((1.0 - gammaHat[i]) * y[i])
            numerSigHat1 = numerSigHat1 + ( (1.0 - gammaHat[i]) * ( y[i] - parms['mu1'] )**2 )
            denomHat1 = denomHat1 + (1.0 - gammaHat[i])

            numerMuHat2 = numerMuHat2 + (gammaHat[i] * y[i])
            numerSigHat2 = numerSigHat2 + (gammaHat[i] * ( y[i] - parms['mu2'] )**2)
            denomHat2 = denomHat2 + gammaHat[i]
            piHat = piHat + (gammaHat[i] / parms['n'])

        ## calculate estimates
        muHat1 = numerMuHat1 / denomHat1
        sigHat1 = numerSigHat1 / denomHat1
        muHat2 = numerMuHat2 / denomHat2
        sigHat2 = numerSigHat2 / denomHat2

        return {'mu1':muHat1, 'mu2':muHat2, 'sig1': sigHat1, 'sig2':sigHat2, 'pi':piHat, 'n':parms['n']}

    def get_likelihood(self,y,parms,gammaHat):
        part1 = 0
        part2 = 0

        for i in range(parms['n']):
            phiTheta1 = stats.norm.pdf(y[i],loc=parms['mu1'],scale=np.sqrt(parms['sig1'])) #r.dnorm(y[i], mean = parms['mu1'], sd = np.sqrt(parms['sig1']))
            phiTheta2 = stats.norm.pdf(y[i],loc=parms['mu2'],scale=np.sqrt(parms['sig2'])) #r.dnorm(y[i], mean = parms['mu2'], sd = np.sqrt(parms['sig2']))
            part1 = part1 + ( (1.0 - gammaHat[i]) * np.log(phiTheta1) + gammaHat[i] * np.log(phiTheta2) )
            part2 = part2 + ( (1.0 - gammaHat[i]) * np.log(parms['pi']) + gammaHat[i] * np.log(1.0 - parms['pi']) )

        return part1 + part2

    def run_em_algorithm(self, numIters, numRuns, verbose = True):
        '''
        main algorithm functions
        '''

        maxLike = -np.inf
        bestEstimates = None

        for j in range(numRuns):

            iterCount = 0
            parms = self.get_init_guesses(self.y)

            ## iterate between E-step and M-step
            while iterCount < numIters:
                iterCount += 1

                ## check to make sure the var estimates are > 0.5
                if parms['sig1'] < 0.0 or parms['sig2'] < 0.0:
                    #print "WARNING: negative variances starting with new intital guesses"
                    iterCount = 1
                    parms = get_init_guesses()

                ## E-step
                gammaHat = self.perform_expectation(self.y,parms)
                logLike = self.get_likelihood(self.y,parms,gammaHat)

                #if self.verbose == True:
                #    print 'iteration',iterCount,'mu1',round(parms['mu1'],2),'mu2',round(parms['mu2'],2),'sig1',round(parms['sig1'],2),
                #    print 'sig2',round(parms['sig2'],2),'pi',round(parms['pi'],2),'obs.data likelihood', round(logLike,4)

                ## M-step
                parms = self.perform_maximization(self.y,parms,gammaHat)

            if logLike > maxLike:
                maxLike = logLike
                bestEstimates = parms.copy()

            if self.verbose == True:
                print('runNum: ',j + 1,'mu1: ',round(parms['mu1'],2),'mu2: ',round(parms['mu2'],2),'sig1: ',round(parms['sig1'],2),)
                print('sig2: ',round(parms['sig2'],2),'pi: ',round(parms['pi'],2),'obs.data likelihood: ', round(logLike,4))

        return maxLike, bestEstimates

if __name__ == '__main__':

    y1 = np.array([-0.39,0.12,0.94,1.67,1.76,2.44,3.72,4.28,4.92,5.53])
    y2 = np.array([ 0.06,0.48,1.01,1.68,1.80,3.25,4.12,4.60,5.28,6.22])
    y  = np.hstack((y1,y2))

    numIters = 25
    numRuns = 20
    verbose = True
    makePlots = True
    tcg = TwoComponentGaussianEM(y, numIters, numRuns,verbose=verbose)

    print('maxLike', tcg.maxLike)
    print('bestEstimates', tcg.bestEst)

    if makePlots == True:
        n, bins, patches = plt.hist(y,15,normed=1,facecolor='gray',alpha=0.75)

        ## add a 'best fit' line (book results)
        mu1 = 4.62
        mu2 = 1.06
        sig1 = 0.87
        sig2 = 0.77

        p1 = mlab.normpdf( bins, mu1, np.sqrt(sig1))
        p2 = mlab.normpdf( bins, mu2, np.sqrt(sig2))
        l1 = plt.plot(bins, p1, 'r--', linewidth=1)
        l2 = plt.plot(bins, p2, 'r--', linewidth=1)

        ## add a 'best fit' line (results from here)
        p3 = mlab.normpdf( bins, tcg.bestEst['mu1'], np.sqrt(tcg.bestEst['sig1']))
        p4 = mlab.normpdf( bins, tcg.bestEst['mu2'], np.sqrt(tcg.bestEst['sig2']))
        l3 = plt.plot(bins, p3, 'k-', linewidth=1)
        l4 = plt.plot(bins, p4, 'k-', linewidth=1)

        plt.xlabel('y')
        plt.ylabel('freq')
        plt.ylim([0,0.8])

        plt.legend( (l1[0], l3[0]), ('Book Estimate', 'My Estimate') )

        plt.savefig('../TwoComponentGauss.png')
        plt.show()


import numpy as np
import warnings
from .function_helper import fill_for_noncomputable_vals
from .catch_errors import check_for_period_error

def simple_moving_average(data, period):
    """
    Simple Moving Average.

    Formula:
    SUM(data / N)
    """
    check_for_period_error(data, period)
    # Mean of Empty Slice RuntimeWarning doesn't affect output so it is
    # supressed
    with warnings.catch_warnings():
        warnings.simplefilter("ignore", category=RuntimeWarning)
        sma = list(map(
            lambda idx:
            np.mean(data[idx-(period-1):idx+1]),
            range(0, len(data))
            ))
    sma = fill_for_noncomputable_vals(data, sma)
    return sma


import numpy as np
import sympy as sy

epsilon=0.0001
maxiteration=100

def main():
    n=10
    # prepare matrix a
    a=np.diag([5.]*n)
    a+=np.diagflat([2.]*(n-1),1)
    a+=np.diagflat([2.]*(n-1),-1)
    print(a)

    b=np.array([3,1,4,0,5,-1,6,-2,7,-15],dtype='f').T
    #initial value x
    x=np.ones(10).T

    D=np.diag(np.diag(a))
    L=np.tril(a,-1)
    U=np.triu(a,+1)

    M= -np.linalg.inv(D+L) @ U
    N=np.linalg.inv(D+L)
    for k in range(maxiteration):
        x_new=M @ x + N @ b
        if(np.linalg.norm(x_new-x) < epsilon):
            break
        x=x_new
    else:
        print("Gauss-Seidel method fail ...")
        exit(1)

    print("the sol of ax = b using Gauss-Seidel method is \n{}".format(x))
    print("iteration {} times".format(k))
    print("indeed ax-b is \n{}".format(a @ x -b))
    print("you can check sol x using sympy...")
    sy_a=sy.Matrix(a)
    sy_x=sy_a.solve(b)
    print(sy_x)

if __name__ == '__main__':
    main()


import numpy as np

__all__ = ['harmonic_tone', 'freq_to_pitch', 'pitch_to_freq']

def harmonic_tone(base_freqs, n_partials=1, profile='exp'):
    """
    Creates a harmonic tone out of one or more base frequencies.

    Input:
    base_freqs - single value, or an numpy array of base frequencies
    n_partials - number of partial in the harmonic tone

    Output:
    Tuple of (freqs, amplitudes).

    Freqs are a 2D array of the frequencies of partials
    of shape (len(freqs), n_partials)

    Amplitudes are of the same shape.

    The amplitude values for a single harmonic tone are going down
    inversely in this case.
    """
    idx = 1 + np.arange(n_partials)
    freqs = np.outer(np.atleast_2d(base_freqs), idx.reshape(1, -1))
    # eg. amplitudes inversely going down
    if profile == 'exp':
        # exponential fall-off
        amp_profile = 0.88 ** idx
    elif profile == 'inverse':
        amp_profile = 1 / idx
    elif profile == 'constant':
        amp_profile = np.ones(len(idx))
    else:
        raise ValueError("Amplitude profile can be ['exp', 'inverse', 'constant'], was", profile)

    amplitudes = np.tile(amp_profile, (len(base_freqs), 1))
    return freqs, amplitudes

def freq_to_pitch(freq, base_freq=440.0, steps_per_octave=12):
    return np.log2(np.array(freq) / base_freq) * steps_per_octave

def pitch_to_freq(pitch, base_freq=440.0, steps_per_octave=12):
    return (2 ** (np.array(pitch) / steps_per_octave)) * base_freq


"""Lineshapes."""

# --- import -------------------------------------------------------------

import numpy as np

from scipy.special import wofz

# --- define -------------------------------------------------------------

__all__ = ["gaussian", "lorentzian_complex", "lorentzian_real", "voigt"]

# --- functions ----------------------------------------------------------

def gaussian(x, x0, FWHM, norm="height"):
    """Calculate a normalized Gaussian lineshape

    Parameters
    ----------
    x : array_like or number
        Input array.
    x0 : array_like or number
        Center of lineshape.
    FHWM : array_like or number
        Full-width-at-half-maximum of lineshape.
    norm : string (optional):
        Type of normalization.
        height specifies that the maximum value is 1.
        area specifies that the lineshape integrates to 1.
        Default is height.

    Returns
    -------
    array_like or number
        Gaussian lineshape.
    """
    c = FWHM / (2 * np.sqrt(2 * np.log(2)))
    arr = np.exp(-1 * (x - x0) ** 2 / (2 * c**2))
    if norm == "height":
        return arr
    elif norm == "area":
        return arr / (c * np.sqrt(2 * np.pi))

def lorentzian_complex(x, x0, G, norm="height_imag"):
    """Calculate a normalized complex Lorentzian lineshape

    Parameters
    ----------
    x : array_like or number
        Input array.
    x0 : array_like or number
        Center of lineshape.
    G : array_like or number
        Half-width-at-half-maximum of lineshape.
    norm : string (optional):
        Type of normalization.
        height_imag specifies that the maximum value of the imaginary component is 1.
        area_int specifies that the square magnitude of the lineshape integrates to 1.
        Default is height_imag.

    Returns
    -------
    array_like or number
        Complex Lorentzian lineshape.
    """
    arr = 1 / (x0 - x - 1j * G)
    if norm == "height_imag":
        return arr * G
    elif norm == "area_int":
        return arr * np.sqrt(G / np.pi)

def lorentzian_real(x, x0, G, norm="height"):
    """Calculate a normalized Lorentzian lineshape

    Parameters
    ----------
    x : array_like or number
        Input array.
    x0 : array_like or number
        Center of lineshape.
    G : array_like or number
        Half-width-at-half-maximum of lineshape.
    norm : string (optional):
        Type of normalization.
        height specifies that the maximum value is 1.
        area specifies that the lineshape integrates to 1.
        Default is height.

    Returns
    -------
    array_like or number
        Lorentzian lineshape.
    """
    arr = G**2 / ((x - x0) ** 2 + G**2)
    if norm == "height":
        return arr
    if norm == "area":
        return arr / (G * np.pi)

def voigt(x, x0, FWHM, G):
    """Calculate an unnormalized Voigt lineshape using Scipy's Faddeeva function

    `Link to Voigt article on Wikipedia`__

    __ https://en.wikipedia.org/wiki/Voigt_profile

    Parameters
    ----------
    x : array_like or number
        Input array.
    x0 : array_like or number
        Center of lineshape.
    FHWM : array_like or number
        Full-width-at-half-maximum of Gaussian part of lineshape.
    G : array_like or number
        Half-width-at-half-maximum of Lorentzian part of lineshape.

    Returns
    -------
    array_like or number
        Voigt lineshape.
    """
    c = FWHM / (2 * np.sqrt(2 * np.log(2)))
    arr = (x - x0 + 1j * G) / (c * np.sqrt(2))
    w = wofz(arr)
    return np.real(w) / (c * np.sqrt(2 * np.pi))


# --------------
#Importing header files
import pandas as pd
import scipy.stats as stats
import math
import numpy as np
import matplotlib.pyplot as plt
from statsmodels.stats.weightstats import ztest
from statsmodels.stats.weightstats import ztest
from scipy.stats import chi2_contingency

import warnings

warnings.filterwarnings('ignore')
#Sample_Size
sample_size=2000

#Z_Critical Score
z_critical = stats.norm.ppf(q = 0.95)

# Critical Value
critical_value = stats.chi2.ppf(q = 0.95, # Find the critical value for 95% confidence*
                      df = 6)   # Df = number of variable categories(in purpose) - 1

#Reading file
data=pd.read_csv(path)

#Code starts here

data_sample = data.sample(n=sample_size,random_state=0)
sample_mean = data_sample['installment'].mean()
sample_std = data_sample['installment'].std()
margin_of_error = z_critical*(sample_std/math.sqrt(sample_size))
confidence_interval = (sample_mean-margin_of_error,sample_mean+margin_of_error)
true_mean = data['installment'].mean()
#print(confidence_interval[0])

if (true_mean >= confidence_interval[0]) and(true_mean <=confidence_interval[1]):
   print( " is in the range")
else :
   print("is outside the given range.")

#Different sample sizes to take
sample_size1=np.array([20,50,100])
#Code starts here
fig ,axes = plt.subplots(nrows = 3 , ncols = 1)
for i in range(len(sample_size1)):
   m=[]
   for j in range(1000):
       a1=data['installment'].sample(n=sample_size1[i])
       m.append(a1.mean())
   mean_series= pd.Series(m)
   axes[i].plot(mean_series)

data['int.rate']=(data['int.rate'].str[:-1].astype(float))/100
#data.head(2)
z_statistic_1 , p_value_1 = ztest(data[data['purpose']=='small_business']['int.rate'],value=data['int.rate'].mean(),alternative='larger')
print(z_statistic_1,p_value_1)

if p_value_1<0.05:
   print("reject null hypothesis")
else:
   print("Accept null hypothesis")

z_statistic_2 , p_value_2 = ztest(data[data['paid.back.loan']=='No']['installment'],data[data['paid.back.loan']=='Yes']['installment'])
print(z_statistic_2,p_value_2)
if p_value_2<0.05:
  print("reject null hypothesis")
else:
  print("Accept null hypothesis")

#Critical value
critical_value = stats.chi2.ppf(q = 0.95, # Find the critical value for 95% confidence*
                     df = 6)   # Df = number of variable categories(in purpose) - 1

#Code starts here
yes= data[data['paid.back.loan']=='Yes']['purpose'].value_counts()
no = data[data['paid.back.loan']=='No']['purpose'].value_counts()
observed = pd.concat([yes.transpose(),no.transpose()],axis=1,keys= ['Yes','No'])
chi2, p, dof, ex = chi2_contingency(observed)
if chi2 > critical_value:
   print("reject the null hypothesis since the two distributions are the same")
else:
   print("null hypothesis cannot be rejected")

import numpy,import scipy,from scipy,from statsmodels


# Implements the power method without using any matrix multiplications, i.e. Monte Carlo approximation to the sum implied by v = Mv
# Author : Cleve Moler, Aleyna Kara
# This function is the Python implementation of  https://github.com/probml/pmtk3/blob/master/demos/pagerankpow.m

import numpy as np
from scipy.sparse import coo_matrix

'''
Returns the PageRank of the graph G and the number of iterations
Arguments:
    G : Adjacency matrix representing the link structure
    p : The probability of a link to be followed.
'''
def pagerank_power_method_sparse(G, p):
    # Link structure
    n, _ = G.shape

    # The fastest way to iterate columns of csc_matrix
    cg = coo_matrix(G)
    L = [[] for i in range(n)]
    for i, j in zip(cg.row, cg.col):
        L[j].append(i)
    c = [len(L[j]) for j in range(n)]

    # Power method
    delta, n_iterations = (1 - p) / n, 0
    x, z = np.ones((n, 1)) / n, np.zeros((n, 1))

    while np.max(np.abs(x - z)) > 1e-4:
        z = x
        x = np.zeros(n)
        for j in range(n):
            if not c[j]:
                x = x + z[j] / n
            else:
                x[L[j]] = x[L[j]] + z[j] / c[j]
        x = p * x + delta
        n_iterations += 1

    return x, n_iterations


import numpy as np

def entropy(y):
    # use numpy.unique to obtain sorted unique elements and their counts
    _, counts = # TODO
    # calculate the proportion of each class in the whole dataset
    # the return value should be an array of proportions
    p = # TODO
    # calculate and return entropy using the formula from the task
    # logarithm can be calculated using the numpy.log2 function
    return # TODO


# demo: GA for TSP with UDF(user defined functions)
import numpy as np
# step1: randomly generate the data
from sko.demo_func import function_for_TSP

num_points, points_coordinate, distance_matrix, cal_total_distance = function_for_TSP(num_points=15)

# step2: DO GA with UDF
from sko.GA import GA_TSP
from sko.GA import selection_tournament, mutation_TSP_1

ga_tsp = GA_TSP(func=cal_total_distance, n_dim=num_points, size_pop=500, max_iter=800, Pm=0.2)
ga_tsp.register('selection', selection_tournament, tourn_size=3). \
    register('mutation', mutation_TSP_1)

best_points, best_distance = ga_tsp.fit()
print('best routine:', best_points, 'best_distance:', best_distance)
# %%
# step3: plot
import matplotlib.pyplot as plt

fig, ax = plt.subplots(1, 1)
best_points_ = np.concatenate([best_points, [best_points[0]]])
best_points_coordinate = points_coordinate[best_points_, :]
ax.plot(best_points_coordinate[:, 0], best_points_coordinate[:, 1], 'o-r')
plt.show()


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

import numpy as np

def calc_line(x_points, y_points):
    assert type(x_points) == list and type(y_points) == list, "x_points and y_points have to be lists"
    assert all([type(x) == int for x in x_points]), "elements of x_points have to be ints"
    assert all([type(y) == int for y in y_points]), "elements of y_points have to be ints"
    assert len(x_points) == len(y_points), "same x_points- and y_points-list length required"
    n_points = len(x_points)

    min_x = 100000
    max_x = 0
    sum_x = 0.0

    a = np.zeros([n_points, 2])
    y = np.zeros([n_points])

    for i in range(n_points):
        y[i] = y_points[i]

        px = x_points[i]
        a[i, 0] = 1.0
        a[i, 1] = px

        min_x = min(px, min_x)
        max_x = max(px, max_x)
        sum_x += px
    if max_x - min_x < 2:
        return sum_x / len(x_points), float("inf")

    return solve_lin(a, y)

def solve_lin(a, y):
    assert isinstance(a, np.ndarray), "a has to np.ndarray"
    assert isinstance(y, np.ndarray), "y has to np.ndarray"

    a_t = np.transpose(a)
    ls = np.matmul(a_t, a)
    rs = np.matmul(a_t, y)
    assert ls.shape == (2, 2)

    det = ls[0, 0] * ls[1, 1] - ls[0, 1] * ls[1, 0]
    if det < 1e-9:
        print("LinearRegression Error: Numerically unstable.")
        return a[0, 1], float("inf")
    else:
        d = 1.0 / det
        inv = np.empty_like(ls)
        inv[0, 0] = d * ls[1, 1]
        inv[1, 1] = d * ls[0, 0]
        inv[1, 0] = -d * ls[1, 0]
        inv[0, 1] = -d * ls[0, 1]

    return np.matmul(inv, rs)

# if __name__ == '__main__':
#     from scipy.stats import linregress
#
#     # (1,30) (10,25) (25, 22) (60,36)
#     xs = [1, 10, 25, 60]
#     ys = [30, 25, 22, 36]
#
#     # # (1,10) (2, 20) (3,15)
#     # x_points = [1, 2, 3]
#     # y_points = [10, 20, 15]
#
#     res = calc_line(xs, ys)
#     res2 = linregress(xs, ys)
#
#     print("res = \n", res)
#     print("res2 = \n", [res[0], res[1]])


"""Linear Regression
https://brohrer.mcknote.com/zh-Hant/how_machine_learning_works/how_linear_regression_works.html
"""

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt

# Parameters
learning_rate = 0.2
training_epochs = 201
display_step = 20

# Create 100 training data
train_X = np.random.rand(100).astype(np.float32)
train_Y = train_X * 0.1 + 0.3

# Try to find values for W and b that compute train_Y = W * train_X + b
# TensorFlow will learns, and best fit is W: [0.1], b: [0.3]
W = tf.Variable(tf.random_uniform([1], -1.0, 1.0))
b = tf.Variable(tf.zeros([1]))
y = W * train_X + b

# Minimize the mean squared errors.
# MMSE reference:
# https://en.wikipedia.org/wiki/Minimum_mean_square_error
# http://allenluadvance.blogspot.tw/2014/01/sine-wave-estimation-mmse-estimator-ml.html
# https://www.khanacademy.org/math/statistics-probability/describing-relationships-quantitative-data/more-on-regression/v/proof-part-1-minimizing-squared-error-to-regression-line
loss = tf.reduce_sum(tf.pow(y-train_Y, 2))/train_X.shape[0]
# loss = tf.reduce_mean(tf.square(y - train_Y)) # Or use reduce_mean
optimizer = tf.train.GradientDescentOptimizer(learning_rate)
train = optimizer.minimize(loss)

# Initialize the variables (i.e. assign their default value)
init = tf.global_variables_initializer()

# Start training
with tf.Session() as sess:

    # Run the initializer
    sess.run(init)

    # Fit all training data
    for step in range(training_epochs):
        sess.run(train)
        if step % display_step == 0:
            stepStr = str(int(step/display_step) + 1) + '.'
            print(stepStr, sess.run(W), sess.run(b))
            plt.plot(train_X, train_Y, 'go', label='Original data')
            plt.plot(train_X, sess.run(W) * train_X + sess.run(b), label='Fitted line')
            plt.legend()
            plt.show()


'''
=====> The function is_prime(num) checks if an input number is a prime number.
=====> The function pirmeFactors(num) computes the prime factors of a given number.

Test number: 600851475143 ---> Required for project euler question 3.

Author: Harivinay V
Github: https://github.com/M87K452b
'''

import math
from numba import jit

@jit(nopython=True)
def is_prime(num):
    '''
    Function: To check if a number is prime
    '''
    if num < 2:
        return False
    if num % 2 == 0 and num > 2:
        return False
    for i in range(3, int(math.sqrt(num)) + 1, 2):
        if num % i == 0:
            return False
    return True

primes = []
factors = []

def primeFactors(num):
    '''
    Function to compute the primefactors of a given number
    '''
    i = 1
    while (num > 2 and i <= num):
        if is_prime(num):
            factors.append(num)
            break
        if is_prime(i):
            if num%i == 0:
                factors.append(i)
                num = num/i
                print(num,'|',i)
        i += 1
    return max(factors)

num=600851475143
largest_primeFactor = primeFactors(num)
print('The largest prime factor of {} is {}'.format(num,largest_primeFactor))


'''
Statistical Computing for Scientists and Engineers
Homework 2
Fall 2018
University of Notre Dame
'''
import numpy as np
import matplotlib.pyplot as plt
from scipy.special import gammaln
import pandas as pd
data = pd.read_csv('data.csv',header=None)
data = np.array(data)
y = data[:,0]
n = data[:,1]
print (y)
N = len(n)
#log-likelihood
def log_likelihood(alpha,beta,y,n):
    '''
    marginal posterior distribution-log_likelihood part
    @args: y = training data, parameters: alpha, beta and dataset:n
    @returns: log_likelihood
    '''
    log_likelihood = 0
    for Y,N in zip(y,n):
	##############################################################
	# INSERT CODE BELOW
	##############################################################
        log_likelihood+=
	##############################################################
	# INSERT CODE ABOVE
	##############################################################

    return log_likelihood

def log_prior(A,B):
    '''
    marginal posterior distribution-log_prior part
    @args: parameters: alpha, beta
    @returns: prior
    '''
    ##############################################################
    # INSERT CODE BELOW
    ##############################################################
    log_prior =
    ##############################################################
    # INSERT CODE ABOVE
    ##############################################################
    return log_prior

def to_beta(x,y):

    return np.exp(y)/(np.exp(x)+1)

def to_alpha(x,y):

    return np.exp(x)*trans_to_beta(x,y)

X,Y = np.meshgrid(np.arange(-2.3,-1.3,0.01),np.arange(1,5,0.01))
param_space = np.c_[X.ravel(), Y.ravel()]
df= pd.DataFrame(param_space, columns=['X','Y'])

df['alpha']= to_alpha(df.X,df.Y)
df['beta'] = to_beta(df.X,df.Y)

df['log_posterior'] = log_prior(df.alpha,df.beta) + log_likelihood(df.alpha,df.beta, y,n)
df['log_jacobian'] = np.log(df.alpha) + np.log(df.beta)

df['transformed'] = df.log_posterior+df.log_jacobian
df['exp_trans'] = np.exp(df.transformed - df.transformed.max())

surface = df.set_index(['X','Y']).exp_trans.unstack().values.T

fig, ax = plt.subplots(figsize = (8,8),facecolor='white')
ax.contourf(X,Y, surface)
ax.set_xlabel(r'$\log(\alpha/\beta)$', fontsize = 16)
ax.set_ylabel(r'$\log(\alpha+\beta)$', fontsize = 16)
ix_z,ix_x = np.unravel_index(np.argmax(surface, axis=None), surface.shape)
print ('x:co-ordinate_value:', np.round(X[0,ix_x],2))
print ('y:co-ordinate_value:', np.round(Y[ix_z,0],2))
ax.scatter([X[0,ix_x]], [Y[ix_z,0]], color = 'red')

text= r"$({a},{b})$".format(a = np.round(X[0,ix_x],2), b = np.round(Y[ix_z,0],2))

ax.annotate(text,xy = (X[0,ix_x],Y[ix_z,0]), xytext=(-1.6, 3.5),
            ha = 'center',
            fontsize = 16,
            color = 'white',
            arrowprops=dict(facecolor='black',));
plt.savefig('HW2-P1b.png', facecolor=fig.get_facecolor(), transparent=True)
plt.show()


import numpy as np

def exp_rate_cumprod(cumprod: list, rate_init: float, d_rate: float):
    """Exponential Model.
    This function calculates rate from cumulative production.

    Parameters
    ---
    cumprod : list, ndarray
        cumulative production
    rate_init : float
        initial rate
    d_rate : float
        decline rate
    Return
    ---
    rate : ndarray
        production rate
    """
    cumprod = np.asarray(cumprod)
    return rate_init - d_rate * cumprod

def exp_rate_time(time: list, rate_init: float, d_rate: float):
    """Exponential Model.
    This function calculates rate from time.

    Parameters
    ---
    time : list, ndarray
        time series
    rate_init : float
        initial rate
    d_rate : float
        decline rate
    Return
    ---
    rate : ndarray
        production rate
    """
    time = np.asarray(time)
    return rate_init * np.exp(-d_rate * time)

def exp_cumprod_rate(rate: list, rate_init: float, d_rate: float):
    """Exponential Model.
    This function calculates cumulative production from rate.

    Parameters
    ---
    rate : list, ndarray
        production rate
    rate_init : float
        initial rate
    d_rate : float
        decline rate
    Return
    ---
    cumprod : ndarray
        cumulative production
    """
    rate = np.asarray(rate)
    return (rate_init - rate)/d_rate

def exp_cumprod_time(time: list, rate_init: float, d_rate: float):
    """Exponential Model.
    This function calculates cumulative production from time.

    Parameters
    ---
    time : list, ndarray
        time series
    rate_init : float
        initial rate
    d_rate : float
        decline rate
    Return
    ---
    cumprod : ndarray
        cumulative production
    """
    raise NotImplementedError()

def exp_time_cumprod(cumprod: list, rate_init: float, d_rate: float):
    """Exponential Model.
    This function calculates time from cumulative production.

    Parameters
    ---
    cumprod : list, ndarray
        cumulative production
    rate_init : float
        initial rate
    d_rate : float
        decline rate
    Return
    ---
    time : ndarray
        time series
    """
    raise NotImplementedError()

def exp_time_rate(rate: list, rate_init: float, d_rate: float):
    """Exponential Model.
    This function calculates time from rate.

    Parameters
    ---
    rate : list, ndarray
        production rate
    rate_init : float
        initial rate
    d_rate : float
        decline rate
    Return
    ---
    time : ndarray
        time series
    """
    rate = np.asarray(rate)
    return np.log(rate_init/rate) / d_rate

def har_rate_cumprod(cumprod: list, rate_init: float, d_rate: float):
    """Harmonic Model.
    This function calculates rate from cumulative production.

    Parameters
    ---
    cumprod : list, ndarray
        cumulative production
    rate_init : float
        initial rate
    d_rate : float
        decline rate
    Return
    ---
    rate : ndarray
        production rate
    """
    cumprod = np.asarray(cumprod)
    return np.exp(np.log(rate_init) - d_rate * cumprod / rate_init)

def har_rate_time(time: list, rate_init: float, d_rate: float):
    """Harmonic Model.
    This function calculates rate from time.

    Parameters
    ---
    time : list, ndarray
        time series
    rate_init : float
        initial rate
    d_rate : float
        decline rate
    Return
    ---
    rate : ndarray
        production rate
    """
    time = np.asarray(time)
    return rate_init / (1 + d_rate * time)

def har_cumprod_rate(rate: list, rate_init: float, d_rate: float):
    """Harmonic Model.
    This function calculates cumulative production from rate.

    Parameters
    ---
    rate : list, ndarray
        production rate
    rate_init : float
        initial rate
    d_rate : float
        decline rate
    Return
    ---
    cumprod : ndarray
        cumulative production
    """
    rate = np.asarray(rate)
    return np.log(rate_init/rate)*rate_init/d_rate

def har_cumprod_time(time: list, rate_init: float, d_rate: float):
    """Harmonic Model.
    This function calculates cumulative production from time.

    Parameters
    ---
    time : list, ndarray
        time series
    rate_init : float
        initial rate
    d_rate : float
        decline rate
    Return
    ---
    cumprod : ndarray
        cumulative production
    """
    raise NotImplementedError()

def har_time_rate(rate: list, rate_init: float, d_rate: float):
    """Harmonic Model.
    This function calculates time from rate.

    Parameters
    ---
    rate : list, ndarray
        production rate
    rate_init : float
        initial rate
    d_rate : float
        decline rate
    Return
    ---
    time : ndarray
        time series
    """
    rate = np.asarray(rate)
    return (1./rate - 1./rate_init) * rate_init/d_rate

def har_time_cumprod(cumprod: list, rate_init: float, d_rate: float):
    """Harmonic Model.
    This function calculates time from cumulative production.

    Parameters
    ---
    cumprod : list, ndarray
        cumulative production
    rate_init : float
        initial rate
    d_rate : float
        decline rate
    Return
    ---
    time : ndarray
        time series
    """
    raise NotImplementedError()

def hyp_rate_cumprod(cumprod: list, rate_init: float, d_rate: float, b_exp: float):
    """Hyperbolic Model.
    This function calculates rate from cumulative production.

    Parameters
    ---
    cumprod : list, ndarray
        cumulative production
    rate_init : float
        initial rate
    d_rate : float
        decline rate
    Return
    ---
    rate : ndarray
        production rate
    """
    cumprod = np.asarray(cumprod)
    const = rate_init/(d_rate * (1 - b_exp))
    return np.exp(np.log(1 - cumprod/const)/(1 - b_exp) + np.log(rate_init))

def hyp_rate_time(time: list, rate_init: float, d_rate: float, b_exp: float):
    """Hyperbolic Model.
    This function calculates rate from time.

    Parameters
    ---
    time : list, ndarray
        time series
    rate_init : float
        initial rate
    d_rate : float
        decline rate
    Return
    ---
    rate : ndarray
        production rate
    """
    time = np.asarray(time)
    return rate_init / np.power(1 + b_exp*d_rate*time, 1/b_exp)

def hyp_cumprod_rate(rate: list, rate_init: float, d_rate: float, b_exp: float):
    """Hyperbolic Model.
    This function calculates cumulative production from rate.

    Parameters
    ---
    rate : list, ndarray
        production rate
    rate_init : float
        initial rate
    d_rate : float
        decline rate
    Return
    ---
    cumprod : ndarray
        cumulative production
    """
    rate = np.asarray(rate)
    const = rate_init/(d_rate * (1 - b_exp))
    return const * (1 - np.power(rate/rate_init, (1 - b_exp)))

def hyp_cumprod_time(time: list, rate_init: float, d_rate: float, b_exp: float):
    """Hyperbolic Model.
    This function calculates cumulative production from time.

    Parameters
    ---
    time : list, ndarray
        time series
    rate_init : float
        initial rate
    d_rate : float
        decline rate
    Return
    ---
    cumprod : ndarray
        cumulative production
    """
    raise NotImplementedError()

def hyp_time_rate(rate: list, rate_init: float, d_rate: float, b_exp: float):
    """Hyperbolic Model.
    This function calculates time from rate.

    Parameters
    ---
    rate : list, ndarray
        production rate
    rate_init : float
        initial rate
    d_rate : float
        decline rate
    Return
    ---
    time : ndarray
        time series
    """
    rate = np.asarray(rate)
    return (np.exp(b_exp*(np.log(rate_init) - np.log(rate))) - 1)/(b_exp * d_rate)

def hyp_time_cumprod(cumprod: list, rate_init: float, d_rate: float, b_exp: float):
    """Harmonic Model.
    This function calculates time from cumulative production.

    Parameters
    ---
    cumprod : list, ndarray
        cumulative production
    rate_init : float
        initial rate
    d_rate : float
        decline rate
    Return
    ---
    time : ndarray
        time series
    """
    raise NotImplementedError()


import os
import numpy as np
from scipy.io import loadmat
import scipy.optimize as op
from ex3_utils import displayData, sigmoid

## Machine Learning Online Class - Exercise 3 | Part 1: One-vs-all

def lrCostFunction(theta, X, y, _lambda):
    m = y.size
    reg = _lambda/m * theta; reg[0] = 0
    hx = sigmoid(X @ theta)
    J = (- y @ np.log(hx) - (1 - y) @ np.log(1 - hx))/m + (reg @ reg)/2
    grad = X.T @ (hx - y) / m + reg
    return (J, grad)

def oneVsAll(X, y, num_labels, _lambda):
    X = np.c_[np.ones(X.shape[0]), X]
    theta = np.zeros((num_labels, X.shape[1]))
    for i in range(1, num_labels+1):
        label = (y == i).astype(int) #y is loaded from mat file and values from 1 to 10
        Result = op.minimize(fun = lrCostFunction, x0 = np.zeros(X.shape[1]), args = (X, label, _lambda), method = 'TNC', jac = True)
        theta[i-1:] = Result.x
    return theta

def predictOneVsAll(all_theta, X):
    X = np.c_[np.ones(X.shape[0]), X]
    pred = np.argmax(sigmoid(X @ all_theta.T), axis=1)
    return pred + 1
# =========== Part 1: Loading and Visualizing Data =============
#  We start the exercise by first loading and visualizing the dataset.
#  You will be working with a dataset that contains handwritten digits.

# Load Training Data
print('Loading and Visualizing Data ...')
scriptdir = os.path.dirname(os.path.realpath(__file__))
data = loadmat(scriptdir + '//ex3data1.mat') # training data stored in arrays X, y
X = data['X']
y = data['y'].ravel()
num_labels = 10          # 10 labels, from 1 to 10
                         # note that we have mapped "0" to label 10
m, input_layer_size = X.shape # 5000 , 400 = 20x20 Input Images of Digits

# Randomly select 100 data points to display
sel = np.random.choice(m, 100, replace=False)
displayData(X[sel, :])

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

# ============ Part 2a: Vectorize Logistic Regression ============

# Test case for lrCostFunction
print('\nTesting lrCostFunction() with regularization')

theta_t = np.array([-2, -1, 1, 2])
X_t = np.c_[np.ones(5), np.arange(1, 16).reshape((5,3), order='F')/10]
y_t = np.array([1, 0, 1, 0, 1])
lambda_t = 3
J, grad = lrCostFunction(theta_t, X_t, y_t, lambda_t)

print(f'\nCost: {J}')
print('Expected cost: 2.534819')
print('Gradients:\n')
print(grad)
print('Expected gradients:')
print(' 0.146561\n -0.548558\n 0.724722\n 1.398003')
input('Program paused. Press enter to continue.\n')

# ============ Part 2b: One-vs-All Training ============
print('\nTraining One-vs-All Logistic Regression...')
_lambda = 0.1
all_theta = oneVsAll(X, y, num_labels, _lambda)
input('Program paused. Press enter to continue.\n')

# ================ Part 3: Predict for One-Vs-All ================

pred = predictOneVsAll(all_theta, X)

print(f'Training Set Accuracy: {np.mean(pred == y) * 100}\n')


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

import numpy as np
import nose
import array_calculus as ac

def test_derivative():
	"""Testing our derivative matrix for three point of an exponential function"""
	# Testing for derivative of exponential at points x=0,1,2
	actual = np.array([(np.exp(1)-np.exp(0)), (np.exp(2)-np.exp(0))/2, (np.exp(2)-np.exp(1))])
	# Testing implementation
	def exponential():
		t = np.linspace(0,2,3)
		ex = np.vectorize(np.exp)
		ex = ex(t)
		return ex
	trial = np.dot(ac.derivative(0,2,3),exponential())
	# Debug message
	print("Should be: ",actual," but returned this: ",trial)
	for m in range(3):
		nose.tools.assert_almost_equal(actual[m],trial[m],4)

def test_second_derivative():
	"""Testing our second derivative matrix for five points of the exponential function"""
	# Testing the second derivative at x = 0,1,2,3,4
	actual = np.array([1.47625,6.96536,10.20501, 25.82899, 10.90807])
	# Testing impementation
	def exponential():
		t = np.linspace(0,4,5)
		ex = np.vectorize(np.exp)
		ex = ex(t)
		return ex
	trial = np.dot(ac.second_derivative(0,4,5),exponential())
	# Debug message
	print("Should be: ",actual," but returned this ",trial)
	for m in range(5):
		nose.tools.assert_almost_equal(actual[m],trial[m],4)