import math
import scipy.stats as st
import numpy as np
import pandas as pd
from scipy.stats import shapiro
from scipy.stats import pearsonr
from scipy.stats import spearmanr
from scipy.stats import kendalltau
from tools import get_type_columns
from sklearn.feature_selection import f_regression, mutual_info_regression

# CALCULATE Z VALUE
def get_z(confidence_level:float)->float:
    """
    Calculate Z value for a given confidence level.

    confidence_level -- confidence level into percent.
    return -- z value.
    """
    return st.norm.ppf(1-(1-confidence_level/100.)/2)

# CALCULATE THE SAMPLE SIZE
def sample_size(population_size:int, confidence_level:float, confidence_interval:float)->int:
    """
    Calculate the sample size using the Cochran’s Sample Size Formula.

    population_size -- the total population size.
    confidence_level -- the seleceted confidence level in percent.
    confidence_interval -- the selected confidence interval in percent.
    return -- sample size with the correction for smaller population (no large).
    """
    Z = 0.0
    p = 0.5
    e = confidence_interval/100.0
    N = population_size
    n_0 = 0.0
    n = 0.0

    # FIND THE NUM STD DEVIATIONS FOR THAT CONFIDENCE LEVEL
    Z = get_z(confidence_level)

    if Z == 0.0:
        return -1

    # CALC SAMPLE SIZE
    n_0 = ((Z**2) * p * (1-p)) / (e**2)

    # ADJUST SAMPLE SIZE FOR FINITE POPULATION
    n = n_0 / (1 + ((n_0 - 1) / float(N)) )

    return int(math.ceil(n)) # THE SAMPLE SIZE

## Tests whether a data sample has a Gaussian distribution according Shapiro test
def test_shapiro(data:np.array, significance:float = 0.05, verbose:bool = False) ->bool:
    """
    Tests whether a data sample has a Gaussian distribution according Shapiro test.

    Parameters
    ----------
    data : np.array()
        Data to be tested.
    significance : float, optional
        Level of significance. The default is 0.05.
    verbose : bool, optional
        Display information or not. The default is False.

    Returns
    -------
    bool
        If data has a Gaussian distribution or not.

    """
    # estimate cofindence level
    confidence = (1 - significance) * 100
    # test
    stat, p = shapiro(data)
    # display
    if verbose:
        print('stat=%.3f, p=%.3f' % (stat, p))
    # check result and return
    if p > significance:
        if verbose:
            print(f'Probably Gaussian (confidence level = {confidence}%)')
        return True
    else:
        if verbose:
            print(f'Probably not Gaussian (confidence level = {confidence}%)')
        return False

## Normality test analysis for several columns in a dataframe
def analysis_normality(df:pd.DataFrame, numerical_columns: list, significance:float = 0.05, verbose:bool = False)->(dict,list):
    """
    Normality test analysis for several columns in a dataframe.

    Parameters
    ----------
    df : pd.DataFrame
        Dataframe to be tested.
    numerical_columns : list
        Variables to be tested.
    significance : float, optional
        Level of significance. The default is 0.05.
    verbose : bool, optional
        Display information. The default is False.

    Returns
    -------
    (dict,list)
        Results of test stored in a dictionary. List of reports.

    """

    # validate columns
    for c in numerical_columns:
        assert c in df.columns.tolist(), f'column "{c}" is required.'
    # estimate cofindence level
    confidence = (1 - significance) * 100
    # initialize
    disnormal = dict()
    lreports = list()
    # loop of columns
    for col in numerical_columns:
        # collect data
        data = df[col].values
        # Shapiro test
        result_shapiro = test_shapiro(data, significance = significance, verbose = verbose)
        # add result
        disnormal[col] = result_shapiro
        # build report
        if result_shapiro:
            sreport = f'"{col}": Probably Gaussian (confidence level = {confidence}%) according to "Shapiro test"'
            # append
            lreports.append(sreport)
        else:
            sreport = f'"{col}": Probably NOT Gaussian (confidence level = {confidence}%) according to "Shapiro test"'
        # display
        if verbose:
            print(sreport)
    # return
    return disnormal, lreports

## Calculate Pearson's coefficient
def correlation_pearson(data1:np.array, data2:np.array, significance:float = 0.05, verbose:bool = False)->float:
    """
    Calculate Pearson's coefficient.

    Parameters
    ----------
    data1 : np.array
        First data array to be used.
    data2 : np.array
        Second data array to be used.
    significance : float, optional
        Level of significance. The default is 0.05.
    verbose : bool, optional
        Display information. The default is False.

    Returns
    -------
    float
        Correlation value.

    """
    # estimate cofindence level
    confidence = (1 - significance) * 100
    # calculate Pearson's correlation
    corr, p = pearsonr(data1, data2)
    # display
    # check result and return
    if p < significance:
        if verbose:
            print("Pearson's correlation: %.3f (confidence interval = %s %s)"%(corr, confidence, '%'))
        return corr
    else:
        if verbose:
            print("Pearson's correlation is not trusted: %.3f (confidence interval = %s %s)"%(corr, confidence, '%'))
        return np.nan

## Calculate a Spearman correlation coefficient
def correlation_spearman(data1:np.array, data2:np.array, significance:float = 0.05, verbose:bool = False)->float:
    """
    Calculate a Spearman correlation coefficient.

    Parameters
    ----------
    data1 : np.array
        First data array to be used.
    data2 : np.array
        Second data array to be used.
    significance : float, optional
        Level of significance. The default is 0.05.
    verbose : bool, optional
        Display information. The default is False.

    Returns
    -------
    float
        Correlation value.

    """
    # estimate cofindence level
    confidence = (1 - significance) * 100
    # calculate Pearson's correlation
    corr, p = spearmanr(data1, data2)
    # display
    # check result and return
    if p < significance:
        if verbose:
            print("Spearman's correlation: %.3f (confidence interval = %s %s)"%(corr, confidence, '%'))
        return corr
    else:
        if verbose:
            print("Spearman's correlation is not trusted: %.3f (confidence interval = %s %s)"%(corr, confidence, '%'))
        return np.nan

## Calculate Kendall’s tau, a correlation measure for ordinal data
def correlation_kendalltau(data1:np.array, data2:np.array, significance:float = 0.05, verbose:bool = False)->float:
    """
    Calculate Kendall’s tau, a correlation measure for ordinal data.

    Parameters
    ----------
    data1 : np.array
        First data array to be used.
    data2 : np.array
        Second data array to be used.
    significance : float, optional
        Level of significance. The default is 0.05.
    verbose : bool, optional
        Display information. The default is False.

    Returns
    -------
    float
        Correlation value.

    """
    # estimate cofindence level
    confidence = (1 - significance) * 100
    # calculate Pearson's correlation
    corr, p = kendalltau(data1, data2)
    # display
    # check result and return
    if p < significance:
        if verbose:
            print("Kendall’s tau correlation: %.3f (confidence interval = %s %s)"%(corr, confidence, '%'))
        return corr
    else:
        if verbose:
            print("Kendall’s tau correlation is not trusted: %.3f (confidence interval = %s %s)"%(corr, confidence, '%'))
        return np.nan

## Calculate a F-test regression (linear dependency)
def f_test_regression(data1:np.array, data2:np.array, significance:float = 0.05, verbose:bool = False)->float:

    # estimate cofindence level
    confidence = (1 - significance) * 100
    # calculate F-test
    corr, p = spearmanr(data1, data2)
    # display
    # check result and return
    if p < significance:
        if verbose:
            print("Spearman's correlation: %.3f (confidence interval = %s %s)"%(corr, confidence, '%'))
        return corr
    else:
        if verbose:
            print("Spearman's correlation is not trusted: %.3f (confidence interval = %s %s)"%(corr, confidence, '%'))
        return np.nan

## Correlation analysis for a couple of columns in a dataframe (for numerical and ordinal data)
def analysis_correlation(data:pd.DataFrame, couple_columns: list, dnormality:dict = None, significance:float = 0.05, verbose:bool = False)->float:
    """
    ## Correlation analysis for a couple of columns in a dataframe (for numerical and ordinal data).

    Parameters
    ----------
    data : pd.DataFrame
        Dataframe to be used.
    couple_columns : list
        Couple of columns names to be used.
    dnormality : dict, optional
        Dictionary with results of normality test per column . The default is None.
    significance : float, optional
        Level of significance. The default is 0.05.
    verbose : bool, optional
        Display information. The default is False.

    Returns
    -------
    float
        Correlation value.

    """

    # validate columns
    for c in couple_columns:
        assert c in data.columns.tolist(), f'column "{c}" is required.'
    # initialize
    col1 = couple_columns[0]
    col2 = couple_columns[1]
    # collect data and remove records with NaN values
    df = data[couple_columns].dropna()
    nsample = len(df)
    v1 = data[col1].values
    v2 = data[col2].values
    # validate type of data
    dtypecols = get_type_columns(df)
    typecol1 = dtypecols[col1]
    typecol2 = dtypecols[col2]
    # clean
    del df

    ## analysis

    # case: ord - ord
    if typecol1 == 'ord' and typecol2 == 'ord':
        # get number of unique values of ordinal variables
        n_unique_var1 = len(list(set(list(v1))))
        n_unique_var2 = len(list(set(list(v2))))
        # select technique
        if n_unique_var1 >= 5 and n_unique_var2 >= 5:
            corr = correlation_spearman(v1, v2, significance = significance, verbose = verbose)
        else:
            corr = correlation_kendalltau(v1, v2, significance = significance, verbose = verbose)
    # case: num - num
    elif typecol1 == 'num' and typecol2 == 'num':
        # get normality
        if dnormality is None:
            is_norm_var1 = False
            is_norm_var2 = False
        else:
            is_norm_var1 = dnormality[col1]
            is_norm_var2 = dnormality[col2]
        # select technique
        if nsample >= 100:
            corr = correlation_pearson(v1, v2, significance = significance, verbose = verbose)
        else:
            if is_norm_var1 and is_norm_var2:
                corr = correlation_pearson(v1, v2, significance = significance, verbose = verbose)
            else:
                corr = correlation_spearman(v1, v2, significance = significance, verbose = verbose)
    # case: num - ord
    elif typecol1 == 'num' and typecol2 == 'ord':
        # get number of unique values of ordinal variables
        n_unique_var2 = len(list(set(list(v2))))
        # select technique
        if n_unique_var2 < 5:
            corr = correlation_kendalltau(v1, v2, significance = significance, verbose = verbose)
        else:
            if nsample >= 100:
                corr = correlation_pearson(v1, v2, significance = significance, verbose = verbose)
            else:
                corr = correlation_spearman(v1, v2, significance = significance, verbose = verbose)
    # case: ord - num
    elif typecol1 == 'ord' and typecol2 == 'num':
        # get number of unique values of ordinal variables
        n_unique_var1 = len(list(set(list(v1))))
        # select technique
        if n_unique_var1 < 5:
            corr = correlation_kendalltau(v1, v2, significance = significance, verbose = verbose)
        else:
            if nsample >= 100:
                corr = correlation_pearson(v1, v2, significance = significance, verbose = verbose)
            else:
                corr = correlation_spearman(v1, v2, significance = significance, verbose = verbose)
    # other case
    else:
        corr = np.na
        # display
        if verbose:
            print('It was not possible to identify correctly columns types.')
    # return
    return corr


#
# Valuation of European Call Options in Black-Scholes-Merton Model
# Including Vega Function and implied volatility Estimation
# bsm_functions.py
#

# Analytical Black-Scholes-Merton (BSM) Formula

def bsm_call_value(S0, K, T, r, sigma):
    """
    Valuation of European call option in BSM model.

    Parameters
    ==========
    s0 : Float
      initial stock/index level
    K : Float
      Strike Price
    T: Float
      Constant risk-free short rate
    sigma: Float
      Volatility Factor in Diffusion Term

    Returns
    =======

    value: Float
      Present value of the European call option]
    """

    from math import log, sqrt, exp
    from scipy import stats

    s0 = float(s0)
    d1 = (log(s0/ K) + (r + 0.5 * sigma ** 2) * T) / (sigma * sqrt(T))
    d2 = (log(s0/ K) + (r - 0.5 * sigma ** 2) * T) / (sigma * sqrt(T))
    value = (s0 * stats.norm.cdf(d1, 0.0, 1.0)
            - K * exp(-r * T) * stats.norm.cdf(d2, 0.0, 1.0))

    # stats.norm.cdf -> Cumulative distribution function for normal distribution
    #

    return value

# Vega Function

def bsm_vega(S0, K, T, r, sigma):
    """
    Vega of european option in BSM Model.

    Parameters
    ==========
    s0 : Float
        initial stock/index level
    K : Float
        strike price
    T : Float
        Maturity date (in year fractions)
    r : float
        constant risk-free short rate
    sigma : float
        volatility factor in diffusion term
    Returns
    =======
    vega : Float
        Partial derivative of BSM formula with respect to sigma, i.e. Vega
    """

    from math import log, sqrt
    from scipy import stats

    S0 = float(S0)
    d1 = (log(S0 / K) + (r + 0.5 * sigma ** 2) * T / (sigma * sqrt(T))
    vega = S0 * stats.normcdf(d1, 0.0, 1.0) * sqrt(T)
    return vega

# Implied volatility function

def bsm_call_imp_vol(S0, K, T, r, C0, sigma_est, it = 100):
    """
    Implied volatility of European call option in BSM model

    Parameters
    ==========
    S0 : Float
        Initial stock/index level
    K : Float
        Strike Price
    T : Float
        Maturity Date (in year fractions)
    r : Float
        Constant risk-free short rate
    sigma_est : Float
        Estimate of impl. volatility
    it : integer
        Number of iterations

    Returns
    =======
    sigma_est : Float
        Numerically estimated implied volatility
    """
    for i in range(it):
        sigma_est -= ((bsm_call_value(S0, K, T, r, sigma_est) - C0)
                        / bsm_vega(S0, K, T, r, sigma_est))
    return sigma_est


import math
from IntegralMethods.RectangleIntegration import leftrectangle, rightrectangle
from IntegralMethods.TrapezoidIntegration import trapezoid
from IntegralMethods.SimpsonIntegration import simpson
from math import sin, exp, pi
import numpy as np
import matplotlib.pyplot as plt

leftrect = []
rightrect = []
trapez = []
simps = []
sol = (2/13)+(3/13*np.e**(3/4*np.pi))
step = [10**0,10**-1,10**-2,10**-3,10**-4, 10**-5,10**-6,10**-7,10**-8]

def f(x):
    return np.e**(3*x)*np.sin(2*x)

if __name__ == "__main__":

    for i in step:
        leftrect.append(abs(sol - leftrectangle(0, pi/4, i, f)))
        rightrect.append(abs(sol - rightrectangle(0, pi/4, i, f)))
        trapez.append(abs(sol - trapezoid(0, pi/4, i, f)))
        simps.append(abs(sol-simpson(0, pi/4, i, f)))

    print(leftrect)
    print(rightrect)
    print(trapez)
    print(simps)

    plt.loglog(step, leftrect)
    plt.loglog(step, rightrect)
    plt.loglog(step, trapez)
    plt.loglog(step, simps)
    plt.legend(["Left", "Right", "Trap","Simpson"])
    plt.ylim([10**-9,10])
    plt.xlabel("h")
    plt.ylabel("Error")
    plt.xlim([10,10**-8])
    plt.show()


import numpy as np

def check_linearity_independent(matrix):
    (m, n) = matrix.shape
    if m != n:
        # Ta có ma trận A không là ma trận vuông
        # Tính hạng của ma trận A
        RA = np.linalg.matrix_rank(matrix)
        if RA == m:
            return True
        if RA < m:
            return False

    if m == n:
        # Ta có ma trận A là ma trận vuông
        # Tính định thức của ma trận A
        det = np.linalg.det(matrix)
        if det != 0:
            return True
        elif det == 0:
            return False

# Test :v
u1 = np.array([-1, 2, -1, 2])
u2 = np.array([2, 2, -4, 2])
u3 = np.array([1, 3, 1, 2])

# Hãy kiểm tra xem u1 , u2 , u3 độc lập tuyến tính hay phụ thuộc tuyến tính?

matrix = np.array([u1.T, u2.T, u3.T])

print(check_linearity_independent(matrix))


'''
Average versus median
100xp
You now know how to use numpy functions to get a better feeling for your data.
It basically comes down to importing numpy and then calling several simple functions
on the numpy arrays:

import numpy as np
x = [1, 4, 8, 10, 12]
np.mean(x)
np.median(x)
The baseball data is available as a 2D numpy array with 3 columns (height, weight, age)
and 1015 rows. The name of this numpy array is np_baseball. After restructuring the data,
however, you notice that some height values are abnormally high. Follow the instructions
and discover which summary statistic is best suited if you're dealing with so-called outliers.

Instructions
-Create numpy array np_height that is equal to first column of np_baseball.
-Print out the mean of np_height.
-Print out the median of np_height.
'''
# np_baseball is available

# Import numpy
import numpy as np

# Create np_height from np_baseball
np_height = np.array(np_baseball[:,0])

# Print out the mean of np_height
print(np.mean(np_height))

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

Intro to Python for Data Science/NumPy/average-versus-median.py


"""README, Author - Jigyasa Gandhi(mailto:jigsgandhi97@gmail.com)
Requirements:
  - scikit-fuzzy
  - numpy
  - matplotlib
Python:
  - 3.5
"""
# Create universe of discourse in python using linspace ()
import numpy as np
X = np.linspace(start=0, stop=75, num=75, endpoint=True, retstep=False)

# Create two fuzzy sets by defining any membership function (trapmf(), gbellmf(),gaussmf(), etc).
import skfuzzy as fuzz
abc1=[0,25,50]
abc2=[25,50,75]
young = fuzz.membership.trimf(X,abc1)
middle_aged = fuzz.membership.trimf(X,abc2)

# Compute the different operations using inbuilt functions.
one = np.ones(75)
zero = np.zeros((75,))
#1. Union = max(µA(x), µB(x))
union = fuzz.fuzzy_or(X, young, X, middle_aged)[1]
#2. Intersection = min(µA(x), µB(x))
intersection = fuzz.fuzzy_and(X, young, X, middle_aged)[1]
#3. Complement (A) = (1- min(µA(x))
complement_a = fuzz.fuzzy_not(young)
#4. Difference (A/B) = min(µA(x),(1- µB(x)))
difference = fuzz.fuzzy_and(X, young, X, fuzz.fuzzy_not(middle_aged)[1])[1]
#5. Algebraic Sum = [µA(x) + µB(x) – (µA(x) * µB(x))]
alg_sum = young + middle_aged - (young*middle_aged)
#6. Algebraic Product = (µA(x) * µB(x))
alg_product = young*middle_aged
#7. Bounded Sum = min[1,(µA(x), µB(x))]
bdd_sum = fuzz.fuzzy_and(X, one, X, young+middle_aged)[1]
#8. Bounded difference = min[0,(µA(x), µB(x))]
bdd_difference = fuzz.fuzzy_or(X, zero, X, young-middle_aged)[1]

#max-min composition
#max-product composition

# Plot each set A, set B and each operation result using plot() and subplot().
import matplotlib.pyplot as plt

plt.figure()

plt.subplot(4,3,1)
plt.plot(X,young)
plt.title("Young")
plt.grid(True)

plt.subplot(4,3,2)
plt.plot(X,middle_aged)
plt.title("Middle aged")
plt.grid(True)

plt.subplot(4,3,3)
plt.plot(X,union)
plt.title("union")
plt.grid(True)

plt.subplot(4,3,4)
plt.plot(X,intersection)
plt.title("intersection")
plt.grid(True)

plt.subplot(4,3,5)
plt.plot(X,complement_a)
plt.title("complement_a")
plt.grid(True)

plt.subplot(4,3,6)
plt.plot(X,difference)
plt.title("difference a/b")
plt.grid(True)

plt.subplot(4,3,7)
plt.plot(X,alg_sum)
plt.title("alg_sum")
plt.grid(True)

plt.subplot(4,3,8)
plt.plot(X,alg_product)
plt.title("alg_product")
plt.grid(True)

plt.subplot(4,3,9)
plt.plot(X,bdd_sum)
plt.title("bdd_sum")
plt.grid(True)

plt.subplot(4,3,10)
plt.plot(X,bdd_difference)
plt.title("bdd_difference")
plt.grid(True)

plt.subplots_adjust(hspace = 0.5)
plt.show()


# -*- coding: utf-8 -*-
"""
Created on Mon Jun  8 23:41:53 2020

@author: lankuohsing
"""

# In[]
import numpy as np
from w2v_utils import *
# In[]
words, word_to_vec_map = read_glove_vecs('./data/glove.6B.50d.txt')

# In[]
# GRADED FUNCTION: cosine_similarity

def cosine_similarity(u, v):
    """
    Cosine similarity reflects the degree of similarity between u and v

    Arguments:
        u -- a word vector of shape (n,)
        v -- a word vector of shape (n,)

    Returns:
        cosine_similarity -- the cosine similarity between u and v defined by the formula above.
    """

    distance = 0.0

    ### START CODE HERE ###
    # Compute the dot product between u and v (≈1 line)
    dot = np.dot(u,v)
    # Compute the L2 norm of u (≈1 line)
    norm_u = np.sqrt(np.sum(u**2))

    # Compute the L2 norm of v (≈1 line)
    norm_v = np.sqrt(np.sum(v**2))
    # Compute the cosine similarity defined by formula (1) (≈1 line)
    cosine_similarity = dot/(norm_u*norm_v)
    ### END CODE HERE ###

    return cosine_similarity
# In[]
father = word_to_vec_map["father"]
mother = word_to_vec_map["mother"]
ball = word_to_vec_map["ball"]
crocodile = word_to_vec_map["crocodile"]
france = word_to_vec_map["france"]
italy = word_to_vec_map["italy"]
paris = word_to_vec_map["paris"]
rome = word_to_vec_map["rome"]

print("cosine_similarity(father, mother) = ", cosine_similarity(father, mother))
print("cosine_similarity(ball, crocodile) = ",cosine_similarity(ball, crocodile))
print("cosine_similarity(france - paris, rome - italy) = ",cosine_similarity(france - paris, rome - italy))

# In[]
# GRADED FUNCTION: complete_analogy

def complete_analogy(word_a, word_b, word_c, word_to_vec_map):
    """
    Performs the word analogy task as explained above: a is to b as c is to ____.

    Arguments:
    word_a -- a word, string
    word_b -- a word, string
    word_c -- a word, string
    word_to_vec_map -- dictionary that maps words to their corresponding vectors.

    Returns:
    best_word --  the word such that v_b - v_a is close to v_best_word - v_c, as measured by cosine similarity
    """

    # convert words to lowercase
    word_a, word_b, word_c = word_a.lower(), word_b.lower(), word_c.lower()

    ### START CODE HERE ###
    # Get the word embeddings e_a, e_b and e_c (≈1-3 lines)
    e_a, e_b, e_c = (word_to_vec_map[word_a],word_to_vec_map[word_b],word_to_vec_map[word_c])
    ### END CODE HERE ###

    words = word_to_vec_map.keys()
    max_cosine_sim = -100              # Initialize max_cosine_sim to a large negative number
    best_word = None                   # Initialize best_word with None, it will help keep track of the word to output

    # to avoid best_word being one of the input words, skip the input words
    # place the input words in a set for faster searching than a list
    # We will re-use this set of input words inside the for-loop
    input_words_set = set([word_a, word_b, word_c])

    # loop over the whole word vector set
    for w in words:
        # to avoid best_word being one of the input words, skip the input words
        if w in input_words_set:
            continue

        ### START CODE HERE ###
        # Compute cosine similarity between the vector (e_b - e_a) and the vector ((w's vector representation) - e_c)  (≈1 line)
        cosine_sim = cosine_similarity(e_b-e_a,word_to_vec_map[w]-e_c)

        # If the cosine_sim is more than the max_cosine_sim seen so far,
            # then: set the new max_cosine_sim to the current cosine_sim and the best_word to the current word (≈3 lines)
        if cosine_sim > max_cosine_sim:
            max_cosine_sim = cosine_sim
            best_word = w
        ### END CODE HERE ###

    return best_word
# In[]
triads_to_try = [('italy', 'italian', 'spain'), ('india', 'delhi', 'japan'), ('man', 'woman', 'boy'), ('small', 'smaller', 'large')]
for triad in triads_to_try:
    print ('{} -> {} :: {} -> {}'.format( *triad, complete_analogy(*triad,word_to_vec_map)))
# In[]
g = word_to_vec_map['woman'] - word_to_vec_map['man']
print(g)

# In[]
print ('List of names and their similarities with constructed vector:')

# girls and boys name
name_list = ['john', 'marie', 'sophie', 'ronaldo', 'priya', 'rahul', 'danielle', 'reza', 'katy', 'yasmin']

for w in name_list:
    print (w, cosine_similarity(word_to_vec_map[w], g))
# In[]
print('Other words and their similarities:')
word_list = ['lipstick', 'guns', 'science', 'arts', 'literature', 'warrior','doctor', 'tree', 'receptionist',
             'technology',  'fashion', 'teacher', 'engineer', 'pilot', 'computer', 'singer']
for w in word_list:
    print (w, cosine_similarity(word_to_vec_map[w], g))
# In[]
def neutralize(word, g, word_to_vec_map):
    """
    Removes the bias of "word" by projecting it on the space orthogonal to the bias axis.
    This function ensures that gender neutral words are zero in the gender subspace.

    Arguments:
        word -- string indicating the word to debias
        g -- numpy-array of shape (50,), corresponding to the bias axis (such as gender)
        word_to_vec_map -- dictionary mapping words to their corresponding vectors.

    Returns:
        e_debiased -- neutralized word vector representation of the input "word"
    """

    ### START CODE HERE ###
    # Select word vector representation of "word". Use word_to_vec_map. (≈ 1 line)
    e = word_to_vec_map[word]

    # Compute e_biascomponent using the formula given above. (≈ 1 line)
    e_biascomponent = np.dot(e,g)/(np.sum(g**2))*g

    # Neutralize e by subtracting e_biascomponent from it
    # e_debiased should be equal to its orthogonal projection. (≈ 1 line)
    e_debiased = e-e_biascomponent
    ### END CODE HERE ###

    return e_debiased
# In[]
e = "receptionist"
print("cosine similarity between " + e + " and g, before neutralizing: ", cosine_similarity(word_to_vec_map["receptionist"], g))

e_debiased = neutralize("receptionist", g, word_to_vec_map)
print("cosine similarity between " + e + " and g, after neutralizing: ", cosine_similarity(e_debiased, g))
# In[]
def equalize(pair, bias_axis, word_to_vec_map):
    """
    Debias gender specific words by following the equalize method described in the figure above.

    Arguments:
    pair -- pair of strings of gender specific words to debias, e.g. ("actress", "actor")
    bias_axis -- numpy-array of shape (50,), vector corresponding to the bias axis, e.g. gender
    word_to_vec_map -- dictionary mapping words to their corresponding vectors

    Returns
    e_1 -- word vector corresponding to the first word
    e_2 -- word vector corresponding to the second word
    """

    ### START CODE HERE ###
    # Step 1: Select word vector representation of "word". Use word_to_vec_map. (≈ 2 lines)
    w1, w2 = pair[0],pair[1]
    e_w1, e_w2 = word_to_vec_map[w1],word_to_vec_map[w2]

    # Step 2: Compute the mean of e_w1 and e_w2 (≈ 1 line)
    mu = (e_w1+e_w2)/2

    # Step 3: Compute the projections of mu over the bias axis and the orthogonal axis (≈ 2 lines)
    mu_B = np.dot(mu,bias_axis)/(np.sum(bias_axis**2))*bias_axis
    mu_orth = mu-mu_B

    # Step 4: Use equations (7) and (8) to compute e_w1B and e_w2B (≈2 lines)
    e_w1B = np.dot(e_w1,bias_axis)/(np.sum(bias_axis**2))*bias_axis
    e_w2B = np.dot(e_w2,bias_axis)/(np.sum(bias_axis**2))*bias_axis

    # Step 5: Adjust the Bias part of e_w1B and e_w2B using the formulas (9) and (10) given above (≈2 lines)
    corrected_e_w1B = np.sqrt(np.abs(1-np.sum(mu_orth**2)))*(e_w1B-mu_B)/np.sqrt(np.sum(((e_w1-mu_orth)-mu_B)**2))
    corrected_e_w2B = np.sqrt(np.abs(1-np.sum(mu_orth**2)))*(e_w2B-mu_B)/np.sqrt(np.sum(((e_w2-mu_orth)-mu_B)**2))

    # Step 6: Debias by equalizing e1 and e2 to the sum of their corrected projections (≈2 lines)
    e1 = corrected_e_w1B+mu_orth
    e2 = corrected_e_w2B+mu_orth

    ### END CODE HERE ###
    return e1, e2
# In[]
print("cosine similarities before equalizing:")
print("cosine_similarity(word_to_vec_map[\"man\"], gender) = ", cosine_similarity(word_to_vec_map["man"], g))
print("cosine_similarity(word_to_vec_map[\"woman\"], gender) = ", cosine_similarity(word_to_vec_map["woman"], g))
print()
e1, e2 = equalize(("man", "woman"), g, word_to_vec_map)
print("cosine similarities after equalizing:")
print("cosine_similarity(e1, gender) = ", cosine_similarity(e1, g))
print("cosine_similarity(e2, gender) = ", cosine_similarity(e2, g))


import numpy as np

class LinearRegression:

    def __init__(self, x, y, alpha=3e-2, max_epochs=10, epsilon=1e-2,
                 batch_size=10):
        self.x = np.concatenate((np.ones((x.shape[0], 1)), x), axis=1)
        self.y = y
        self.alpha = alpha
        self.maxEpochs = max_epochs
        self.epsilon = epsilon
        self.batchSize = batch_size

        self.history = {
            'theta': [],
            'cost': [],
        }

        self.theta = np.random.normal(loc=0.0, scale=1.0, size=(self.x.shape[1], 1))
        self.history['theta'].append(self.theta.squeeze().tolist())

        initialPrediction = self.getPrediction(self.x, self.theta)
        initialCost = self.getCost(initialPrediction, self.y)
        self.history['cost'].append(initialCost)

        self.prevTheta = self.theta
        self.printStats()

    def printStats(self):
        print('=' * 80)
        print('[INFO]\t\tHyperparameters for Linear Regression')
        print('=' * 80)
        print(f'[INFO] Learning Rate: {self.alpha}')
        print(f'[INFO] Mini Batch Size: {self.batchSize}')
        print(f'[INFO] Maximum Epochs: {self.maxEpochs}')
        print(f'[INFO] Epsilon for checking convergence: {self.epsilon}')
        print(f'[INFO] Starting value of theta: {self.theta.tolist()} | {self.theta.shape}')
        print(f'[INFO] Shape of x data with ones: {self.x.shape}')
        print(f'[INFO] Shape of y data: {self.y.shape}')
        print(f'[INFO] Initial cost: {self.history["cost"][0]}')
        print('=' * 80)

    def runGradientDescent(self):

        xBatches = np.array_split(self.x, self.x.shape[0] // self.batchSize)
        yBatches = np.array_split(self.y, self.y.shape[0] // self.batchSize)

        for i in range(self.maxEpochs):
            for j, (x, y) in enumerate(zip(xBatches, yBatches)):
                # keeping track of prev theta for checking convergence
                self.prevTheta = self.theta

                h = self.getPrediction(x, self.theta)
                cost = self.getCost(h, y)
                gradients = (1 / x.shape[0]) * np.dot(np.transpose(x), (h - y))
                self.theta = self.theta - self.alpha * gradients

                # log metrics
                self.history['theta'].append(self.theta.squeeze().tolist())
                self.history['cost'].append(cost)

                if self.isConverged():
                    print(f'[INFO] Gradient Descent converged at Epoch: {i + 1}, iteration: {j + 1}')
                    break

            if self.isConverged():
                break

    def getThetaByNormalEquations(self):
        return np.dot(np.linalg.inv(np.dot(np.transpose(self.x), self.x)),
                      np.dot(np.transpose(self.x), self.y))

    def isConverged(self):
        return (abs(self.theta - self.prevTheta) <= self.epsilon).all()

    def getHistory(self):
        return self.history

    @staticmethod
    def getPrediction(x, theta):
        return np.dot(x, theta)

    @staticmethod
    def getCost(y_pred, y_true):
        m = y_pred.shape[0]
        return (1 / (2 * m)) * np.sum((y_pred - y_true)**2)


#! python3
# -*- coding:utf-8 -*-
'''
  ユニバーサルファンクション
  map()のように、ndarray内の各要素に一括で処理を行える
'''
import random
import math
import numpy as np

#abs 絶対値に変換する
np.random.seed(123)
print("abs")
l = np.random.randint(-10, 10, 5)
print(type(l))
print(np.abs(l))
#実はndarrayの場合は標準absでもできる。
#標準リストを標準absで処理しようとするとリストじゃないと怒られる。
print(abs(l))
#print(abs([ random.randint(-5,-1) for x in range(5) ]))
print("--------")

#sin, cos
#サイン、コサインに変換する
#度数法(0〜360)ではなく弧度法で指定しないといけない点に注意。
print("sin, cos")
#度数法で角度を設定
l = np.array([0, 30, 60, 90])
#弧度法に変換
l = l / 360 * math.pi * 2
#ユニバーサルファンクションを適用してみる
print(np.sin(l))
print(np.cos(l))
print(np.tan(l))
print("--------")

#おまけ　度数法と弧度法を互いに変換する便利関数がある。
print("radians " + str(np.radians(180)))
print("deg2rad " + str(np.deg2rad(180)))
print("rad2deg " + str(np.rad2deg(3.14)))

#平均、中央値、最瀕値
print("mean, median, mod")
l = np.array([1, 2, 2, 2, 3, 3, 4])
print(np.mean(l))
print(np.median(l))
#print(np.mod(l))
print("--------")

#積
print("prod")
print(np.prod(l))
print("--------")
#幾何平均
print("mean prod")
print(np.prod(l) ** (1/len(l)))
print("--------")

#四捨五入、切り捨て、切り上げ
print("round, trunc, floor, ceil")
# 配列 [-1.7, -1.5, -0.2, 0.2, 1.5, 1.7, 2.0] を作成
a = np.array([-1.7, -1.5, -0.2, 0.2, 1.5, 1.7, 2.0])
# 四捨五入 (小数点以下 .5 以上は繰上げ、.5未満は切捨て)
print(np.round(a))
# 切り捨て (小数部分を取り除く)
print(np.trunc(a))
# 切り捨て (小さい側の整数に丸める)
print(np.floor(a))
# 切り上げ (大きい側の整数に丸める)
print(np.ceil(a))
# ゼロに近い側の整数に丸める
print(np.fix(a))
print("--------")

#最大値、最小値
print("max, min")
print(np.max(a))
print(np.min(a))
print("--------")

#平方根
print("sqrt")
print("before " + str([1, 4, 9, 16]))
print("sqrt " + str(np.sqrt([1, 4, 9, 16])))
print("--------")


import numpy as np
from math import atan2, asin

def Euler2Quaternion(phi, theta, psi):
    cth = np.cos(theta/2)
    cph = np.cos(phi/2)
    cps = np.cos(psi/2)

    sth = np.sin(theta/2)
    sph = np.sin(phi/2)
    sps = np.sin(psi/2)

    e0 = cps*cth*cph+sps*sth*sph
    e1 = cps*cth*sph-sps*sth*cph
    e2 = cps*sth*cph+sps*cth*sph
    e3 = sps*cth*cph+cps*sth*sph
    e = np.array([e0,e1,e2,e3])
    return e

def Quaternion2Euler(e):
    e0 = e.item(0)
    e1 = e.item(1)
    e2 = e.item(2)
    e3 = e.item(3)

    phi = atan2(2*(e0*e1 + e2*e3),(e0**2+e3**2-e1**2-e2**2))
    theta = asin(2*(e0*e2-e1*e3))
    psi = atan2(2*(e0*e3 + e1*e2),(e0**2+e1**2-e2**2-e3**2))
    return [phi,theta,psi]

def Quaternion2Rotation(e):
    e0 = e.item(0)
    e1 = e.item(1)
    e2 = e.item(2)
    e3 = e.item(3)

    R = np.array([[e0**2 + e1**2 - e2**2 - e3**2, 2*(e1*e2 - e0*e3), 2*(e1*e3 + e0*e2)],
                  [2*(e1*e2 + e0*e3), e0**2 - e1**2 + e2**2 - e3**2, 2*(e2*e3 - e0*e1)],
                  [2*(e1*e3 - e0*e2), 2*(e2*e3 + e0*e1), e0**2 - e1**2 - e2**2 + e3**2]
                  ])
    return R

def Euler2Rotation(phi, theta, psi):
    # print("orig:", phi, theta, psi)
    # e = Euler2Quaternion(phi, theta, psi)
    # R = Quaternion2Euler(e)

    cph = np.cos(phi)
    sph = np.sin(phi)
    cth = np.cos(theta)
    sth = np.sin(theta)
    cps = np.cos(psi)
    sps = np.sin(psi)

    Rbv2 = np.array([[1., 0., 0.],\
                    [0., cph, sph],\
                    [0., -sph, cph]])

    Rv2v1 = np.array([[cth, 0., -sth],\
                    [0., 1., 0.],\
                    [sth, 0., cth]])

    Rv1i = np.array([[cps, sps, 0.],\
                    [-sps, cps, 0.],\
                    [0., 0., 1.]])

    R = Rbv2@Rv2v1@Rv1i

    return R.T


# Exercise 3
# The binomial distribution describes the statistics of the number of successful events for a Bernoulli experiment
# repeated N times, where the probability of success of each experiment is p.
# 1. Execute Ntr = 10000 trials, each made of N = 100 Bernoulli experiments with probability of success p = 0.05.
# [Hint: to test whether a Bernoulli experiment is successful or not, draw a random number u ∼ U(0, 1), and check if u ≤ p.]
# 2. For each trial i, count the number of successes si, and draw the empirical probability mass function (PMF)
# of the number of successes throughout all trials. Compare against the theoretical binomial PMF.
# 3. Compare the empirical and the theoretical binomial distributions against a Poisson distribution of parameter λ = N p.
# Repeat the comparison for different values of N and p. When does the Poisson PMF accurately approximate the binomial PMF?

# import
import numpy as np
from matplotlib import pyplot as plt
from numpy import mean, min, max, median, quantile
from scipy.stats import binom, norm, t as student, expon, poisson
from math import sqrt, pow, floor, ceil, exp

# define corrected functions for std and variance
def variance(values):
	return np.var(values, ddof=1)

def std(values):
	return np.std(values, ddof=1)

Ntr = 10000
N = 100
p = 0.05
trials = []
for i in range(Ntr):
	trial = []
	for l in range(N):
		if np.random.rand() <= p:
			trial.append(1)
		else:
			trial.append(0)
	trials.append(trial)

# count successes s_i and draw pmf
trials = np.array(trials)
trial_sums = np.sum(trials, axis=1)
plt.hist(trial_sums, bins = np.arange(0, trial_sums.max() + 1.5) - 0.5, density=True)

# compare against theoretical binomial distribution
X = np.arange(0, 20, 1)
Y = binom.pmf(X, N, p)
plt.plot(X, Y, 'k-', zorder=2)

# compare against a poisson with lambda = N*p
X = np.arange(0, 20, 1)
Y = poisson.pmf(X, N * p)
plt.plot(X, Y, 'r-', zorder=3)

Y = poisson.pmf(X, 2 * p * N)
plt.plot(X, Y, 'm-', zorder=3)

Y = poisson.pmf(X, 4 * p * N)
plt.plot(X, Y, 'y-', zorder=3)
plt.show()


import numpy as np
import pandas as pd
from scipy.spatial.distance import pdist, squareform
from tabulate import tabulate
import random

import networkx as nx
from pygsp import graphs, filters, plotting

#### Network
def gaussian_kernel(dist, sigma):
    return np.exp(-dist**2 / (2*sigma**2))

def get_adjacency(X: np.ndarray, dist_metric, sigma=1, epsilon=0):
    """ X (n x d): coordinates of the n data points in R^d.
        sigma (float): width of the kernel
        epsilon (float): threshold
        Return:
        adjacency (n x n ndarray): adjacency matrix of the graph.
    """
    dist = squareform(pdist(X, metric=dist_metric))
    adjacency = np.exp(- dist ** 2 / (2 * sigma ** 2))
    adjacency[adjacency < epsilon] = 0
    np.fill_diagonal(adjacency, 0)
    return adjacency

def graph_basic_stats(G):
    nodes_number = G.number_of_nodes()
    edges_number = G.number_of_edges()

    g_degree = G.degree()
    sum_degree = sum(dict(g_degree).values())
    average_degree = sum_degree / nodes_number

    tab = [
        ["Number of nodes", nodes_number],
        ["Number of edges", edges_number],
        ["Graph density", round(nx.classes.function.density(G) * 100, 2)],
        ["Average degree", round(average_degree, 2)],
        ["Number of connected components", nx.number_connected_components(G)],
        ["Average clustering coefficient", round(nx.average_clustering(G), 2)],
        ["Diameter of the network (longest shortest path)", nx.diameter(G)]
    ]
    print(tabulate(tab, tablefmt='fancy_grid'))

#### GSP
def compute_laplacian(adjacency: np.ndarray, normalize: bool):
    """ Return:
        L (n x n ndarray): combinatorial or symmetric normalized Laplacian.
    """
    D = np.diag(np.sum(adjacency, 1)) # Degree matrix
    combinatorial = D - adjacency
    if normalize:
        D_norm = np.diag(np.clip(np.sum(adjacency, 1), 1, None)**(-1/2))
        return D_norm @ combinatorial @ D_norm
    else:
        return combinatorial

def spectral_decomposition(laplacian: np.ndarray):
    """ Return:
        lamb (np.array): eigenvalues of the Laplacian
        U (np.ndarray): corresponding eigenvectors.
    """
    return np.linalg.eigh(laplacian)

def fit_polynomial(lam: np.ndarray, order: int, spectral_response: np.ndarray):
    """ Return an array of polynomial coefficients of length 'order'."""
    A = np.vander(lam, order, increasing=True)
    coeff = np.linalg.lstsq(A, spectral_response, rcond=None)[0]
    return coeff

def polynomial_graph_filter(coeff: np.array, laplacian: np.ndarray):
    """ Return the laplacian polynomial with coefficients 'coeff'. """
    power = np.eye(laplacian.shape[0])
    filt = coeff[0] * power
    for n, c in enumerate(coeff[1:]):
        power = laplacian @ power
        filt += c * power
    return filt

#### GCNN
def get_masks(nb_nodes, test_ratio, seed=None):
    ''' Return the indices for the train and test sets
    '''
    if seed is not None:
        np.random.seed(seed)

    nb_test = int(nb_nodes*test_ratio)
    test_mask = np.sort(random.sample(range(0, nb_nodes), nb_test))
    train_mask = list(set(np.arange(0, nb_nodes))^set(test_mask))

    return train_mask, test_mask

def compute_accuracy(y, y_hat):
    assert(len(y)==len(y_hat)), 'y and y_hat must have the same length'
    return np.sum(y_hat == y) / (len(y) - int(pd.DataFrame(y).isna().sum())) # to deal with NaNs


import numpy as np
import cv2 # You must not use any methods which has 'hough' in it!
from utils import  hough_peaks

def hough_lines_vote_acc(edge_img, rho_res=1, thetas= np.arange(0,180)):
    h,w=edge_img.shape[:2]
    d=int(np.round(np.sqrt(h**2+w**2)))
    y,x=np.nonzero(edge_img>0)
    A=np.zeros((2*d+1,len(thetas)))
    thetas1=np.deg2rad(thetas)
    rhos=np.arange(0,2*d)
    #rhos=[]

    for i in range(len(x)):
        for theta in thetas1:
            rho=np.int(np.ceil(x[i]*np.cos(theta)+y[i]*np.sin(theta)))
            A[rho,np.int(np.round(np.rad2deg(theta)))]+=1
            #rhos.append(rho)

    return A, thetas, rhos

def hough_circles_vote_acc(edge_img, radius):
    r=radius
    h,w=edge_img.shape[:2]
    edges=edge_img>0
    y_idxs,x_idxs=np.nonzero(edges)
    A=np.zeros((h,w))
    theta=np.linspace(-180,180,360)
    for i in range(len(x_idxs)):
        x=x_idxs[i]
        y=y_idxs[i]
        for t in theta:
            b=y-r*np.sin(t)
            a=x+r*np.cos(t)
            if a<h and a>0 and b<w and b>0:
                A[int(b),int(a)]+=1

    return A

def find_circles(edge_img, radius_range=[1,2], threshold=100, nhood_size=10):
    """
      A naive implementation of the algorithm for finding all the circles in a range.
      Feel free to write your own more efficient method [Extra Credit].
      For extra credit, you may need to add additional arguments.

      Args
      - edge_img: numpy nd-array of dim (m, n).
      - radius_range: range of radius. All cicles whose radius falls
      in between should be selected.
      - nhood_size: size of the neighborhood from where only one candidate can be chosen.

      Returns
      - centers, and radii i.e., (x, y) coordinates for each circle.

      HINTS:
      - I encourage you to use this naive version first. Just be aware that
       it may take a long time to run. You will get EXTRA CREDIT if you can write a faster
       implementaiton of this method, keeping the method signature (input and output parameters)
       unchanged.
    """
    n = radius_range[1] - radius_range[0]
    H_size = (n,) + edge_img.shape
    H = np.zeros(H_size, dtype=np.uint)
    centers = ()
    radii = np.arange(radius_range[0], radius_range[1])
    valid_radii = np.array([], dtype=np.uint)
    num_circles = 0
    for i in range(len(radii)):
        H[i] = hough_circles_vote_acc(edge_img, radii[i])
        peaks = hough_peaks(H[i], numpeaks=10, threshold=threshold,
                            nhood_size=nhood_size)
        if peaks.shape[0]:
            valid_radii = np.append(valid_radii, radii[i])
            centers = centers + (peaks,)
            for peak in peaks:
                cv2.circle(edge_img, tuple(peak[::-1]), radii[i]+1, (0,0,0), -1)
        #  cv2.imshow('image', edge_img); cv2.waitKey(0); cv2.destroyAllWindows()
        num_circles += peaks.shape[0]
        print('Progress: %d%% - Circles: %d\033[F\r'%(100*i/len(radii), num_circles))
    print('Circles detected: %d          '%(num_circles))
    centers = np.array(centers)
    return centers, valid_radii.astype(np.uint)


from dataclasses import dataclass
import numpy as np
from numpy import linalg as nla, ndarray
from functools import cached_property

from config import DEBUG

def isPSD(arr: np.ndarray) -> bool:
    return np.allclose(arr, arr.T) and np.all(np.linalg.eigvals(arr) >= 0)

@dataclass(frozen=True)
class MultiVarGaussian:
    """A class for using Gaussians"""
    mean: ndarray  # shape=(n,)
    cov: ndarray  # shape=(n, n)

    def __post_init__(self):
        if DEBUG:
            assert self.mean.shape * 2 == self.cov.shape
            assert np.all(np.isfinite(self.mean))
            assert np.all(np.isfinite(self.cov))
            assert isPSD(self.cov)

    @cached_property
    def ndim(self) -> int:
        return self.mean.shape[0]

    @cached_property
    def scaling(self) -> float:
        scaling = (2*np.pi)**(-self.ndim/2) * nla.det(self.cov)**(-1/2)
        return scaling

    def mahalanobis_distance_sq(self, x: np.ndarray) -> float:
        """Calculate the mahalanobis distance between self and x.

        This is also known as the quadratic form of the Gaussian.
        See (3.2) in the book.
        """
        # this method could be vectorized for efficient calls
        error = x - self.mean
        mahalanobis_distance = error.T @ nla.solve(self.cov, error)
        return mahalanobis_distance

    def pdf(self, x):
        density = self.scaling*np.exp(-self.mahalanobis_distance_sq(x)/2)
        return density

    def marginalize(self, idxs):
        return MultiVarGaussian(self.mean[idxs], self.cov[idxs][:, idxs])

    def __iter__(self):  # in order to use tuple unpacking
        return iter((self.mean, self.cov))

    def __eq__(self, o: object) -> bool:
        if not isinstance(o, MultiVarGaussian):
            return False
        return np.allclose(self.mean, o.mean) and np.allclose(self.cov, o.cov)


from __future__ import division
import pandas as pd
import numpy as np
import scipy as sp
import matplotlib.pyplot as plt
import numpy.linalg as npla
import scipy.linalg as spla
import scipy.special

# Code may print some warnings due to pandas in Python2.
# These warning are benign. Verigy here: https://stackoverflow.com/questions/40845304/runtimewarning-numpy-dtype-size-changed-may-indicate-binary-incompatibility

z = 20

J_0 = scipy.special.jv(0, z)
J_1 = scipy.special.jv(1, z)

bessel_val_by_rec = [J_0, J_1]

for i in range(2, 51):

    J_i = ( ( ( ( 2 * ( i - 1 ) ) / z ) * bessel_val_by_rec[i - 1] ) - bessel_val_by_rec[i - 2] )

    bessel_val_by_rec.append(J_i)

bessel_val_by_func = [scipy.special.jv(i, z) for i in range(0, 51)]

relative_err = []
for i in range(2, 51):
    relative_err.append((bessel_val_by_rec[i] - bessel_val_by_func[i])/bessel_val_by_func[i])

# Again, just printing magnitude of the Relative Error
# Comment this value to print just the ratio
relative_err = [abs(i) for i in relative_err]

df = pd.DataFrame({"n" : [i for i in range(2, 51)], "From Function" : bessel_val_by_func[2:], "From Recurrence" : bessel_val_by_rec[2:], "Relative Error" : relative_err}, columns=["n", "From Function", "From Recurrence", "Relative Error"])
print(df.to_string(index_names=False))

plt.xlabel("Value of n")
plt.ylabel("Absolute Value of Relative Error")
plt.plot( np.arange(2, 51), relative_err)
plt.savefig("problem_3b.png")
# Uncomment to show plot
# plt.show()


# coding: utf-8

# In[1]:

import numpy as np
import matplotlib.pyplot as plt
get_ipython().magic('matplotlib inline')

# In[2]:

def logistic(r, x):
    return r * x * (1 - x)

# In[3]:

x = np.arange(0, 1.02,0.02)
plt.plot(x, logistic(2, x), 'b')
plt.show()

# In[10]:

def plot_map(r, x0, n):
    t = np.linspace(0, 1)
    plt.plot(t, logistic(r, t), 'k', lw=2)
    plt.plot([0, 1], [0, 1], 'k', lw=2)
    x = x0
    for i in range(n):
        y = logistic(r, x)
        plt.plot([x, x], [x, y], 'k', lw=1)
        plt.plot([x, y], [y, y], 'k', lw=1)
        plt.plot([x], [y], 'ok', ms=10, alpha=(i + 1) / n)
        x = y

plot_map(2.5, .1, 10)

# In[11]:

plot_map(3.9, .1, 80)

# In[6]:

n = 10000
r = np.linspace(2.5, 4.0, n)

# In[7]:

iterations = 1000
last = 100

# In[8]:

x = 1e-5 * np.ones(n)
lyapunov = np.zeros(n)

# In[9]:

for i in range(iterations):
    x = logistic(r, x)
    if i >= (iterations - last):
        plt.plot(r, x, ',k',alpha=0.25)


from builtins import print

from numpy import *

'''
add any value to each element to the array
arr1 = array([1,2,3,4,7])

arr1+=5
print(arr1)
'''

'''
add two array also called vectorized operation
arr1 = array([1,2,3,4,5])
arr2 = array([6,7,8,9,10])

print("Addition is : " , arr1 + arr2)

'''

arr1 = array([2, 1, 45, 3, 21, 12, 2, 1])
arr2 = array([12, 54, 65, 32, 1, 8, 3, 2, 4])
print("sin : ", sin(arr1))
print("cos : ", cos(arr1))
print("log : ", log(arr1))
print("sqrt : ", sqrt(arr1))
print("sum : ", sum(arr1))
print("min : ", min(arr1))
print("max : ", max(arr1))
# check it print(subtract(arr1-1))
print("sort : ", sort(arr1))
print("unique : ", unique(arr1))
print("concatenate : ", sort(concatenate([arr1, arr2])))
#print("subtract : ",subtract(arr1-1))

# Creating array object
arr = array([[1, 2, 3],
                [4, 2, 5]])

# Printing type of arr object
print("Array is of type: ", type(arr))

# Printing array dimensions (axes)
print("No. of dimensions: ", arr.ndim)

# Printing shape of array rows * cols
print("Shape of array: ", arr.shape)

# Printing size (total number of elements) of array
print("Size of array: ", arr.size)

# Printing type of elements in array
print("Array stores elements of type: ", arr.dtype)


# This example describe how to integrate ODEs with scipy.integrate module and how
# to use the matplotlib module to plot trajectories, directions field and others
# useful informations.
#
# == Presentation of the Lokta-Volterra Model ==
#
#
# We will have a look at the Lokta-Volterra model, laso known as the
# predator-prey equations, re a pair of first order, non-linear, differential
# equations frequently used to describe the dynamics of biological systems in
# which two species interact, one a predator and one its prey. They were proposed
# independently by Alfred J. Lotka in 1925 and Vito Volterra in 1926 :
# du/dt =  a*u -   b*u*v
# dv/dt = -c*v + d*b*u*v
#
# with the following notations :
#
# *  u : number of prey (for example rabbits)
#
# *  v : number of predators (for example foxes)
#
# * a, b, c, d are constant parameters defining the behavior of the population :
#
#   + a is the natural growing rate of rabbits, when there's no foxes
#
#   + b is the natural dying rate of rabbits, due to predation
#
#   + c is the natural dying rate of foxes, when there's no rabbits
#
#   + d is the factor descibing how many catched rabbits let create new rabbits
#
#
# We will use X=[u, v] to describe the state of both populations.
# Definition of the equations:
#
from numpy import *
import pylab as p

# Parameters
a = 1.
b = 0.1
c = 1.5
d = 0.75

def dX_dt(X, t=0):
    """ Return the growth rate of foxes and rabbits populations. """
    return array([ a*X[0] -   b*X[0]*X[1] ,
                  -c*X[1] + d*b*X[0]*X[1] ])
#
# === Population equilibrium ===
#
# Before using scipy to integrate this system, we will have a closer look on
# position equilibrium. Equilibrium occurs when the growth rate is equal to 0.
# This gives two fixed points:
#
X_f0 = array([0., 0.])
X_f1 = array([ c/(d*b), a/b])
all(dX_dt(X_f0) == zeros(2) ) and all(dX_dt(X_f1) == zeros(2)) # => True
#
# === Stability of the fixed points ===
# Near theses two points, the system can be linearized :
# dX_dt = A_f*X where A is the Jacobian matrix evaluated at the corresponding point.
# We have to define the Jacobian matrix:
#
def d2X_dt2(X, t=0):
    """ Return the jacobian matrix evaluated in X. """
    return array([[a -b*X[1],   -b*X[0]     ],
                  [b*d*X[1] ,   -c +b*d*X[0]] ])
#
# So, near X_f0, which represents the extinction of both species, we have:
# A_f0 = d2X_dt2(X_f0)                    # >>> array([[ 1. , -0. ],
#                                         #            [ 0. , -1.5]])
#
# Near X_f0, the number of rabbits increase and the population of foxes decrease.
# X_f0 is a [http://en.wikipedia.org/wiki/Saddle_point saddle point].
#
# Near X_f1, we have :
A_f1 = d2X_dt2(X_f1)                    # >>> array([[ 0.  , -2.  ],
                                        #            [ 0.75,  0.  ]])

# whose eigenvalues are +/- sqrt(ca).j :
lambda1, lambda2 = linalg.eigvals(A_f1) # >>> (1.22474j, -1.22474j)

# They are imaginary number, so the fox and rabbit populations are periodic and
# their period is given by :
T_f1 = 2*pi/abs(lambda1)                # >>> 5.130199
#
# == Integrating the ODE using scipy.integate ==
#
# Now we will use the scipy.integrate module to integrate the ODE.
# This module offers a  method named odeint, very easy to use to integrade ODE:
#
from scipy import integrate

t = linspace(0, 15,  1000)              # time
X0 = array([10, 5])                     # initials conditions: 10 rabbits and 5 foxes

X, infodict = integrate.odeint(dX_dt, X0, t, full_output=True)
infodict['message']                     # >>> 'Integration successful.'
#
# `infodict` is optionnal, and you can omit the `full_output` argument if you don't want it.
# type "info(odeint)" if you want more information about odeint inputs and outputs.
#
# We will use matplotlib to plot the evolution of both populations:
#
rabbits, foxes = X.T

f1 = p.figure()
p.plot(t, rabbits, 'r-', label='Rabbits')
p.plot(t, foxes  , 'b-', label='Foxes')
p.grid()
p.legend(loc='best')
p.xlabel('time')
p.ylabel('population')
p.title('Evolution of fox and rabbit populations')
f1.savefig('rabbits_and_foxes_1.png')
#
#
# The populations are indeed periodic, and their period is near to the T_f1 we calculated.
#
# == Plotting directions field and trajectories in the phase plane ==
#
# We will plot some trajectories in a phase plane for different starting
# points between X__f0 and X_f1.
#
# We will ue matplotlib's colormap to define colors for the trajectories.
# These colormaps are very useful to make nice plots.
# Have a look on ShowColormaps if you want more information.
#
values = linspace(0.3, 0.9, 5)                          # position of X0 between X_f0 and X_f1
vcolors = p.cm.Greens(linspace(0.3, 1., len(values)))   # colors for each trajectory

f2 = p.figure()

#-------------------------------------------------------
# plot trajectories
for v, col in zip(values, vcolors):
    X0 = v * X_f1                               # starting point
    X = integrate.odeint( dX_dt, X0, t)         # we don't need infodict here
    p.plot( X[:,0], X[:,1], lw=3.5*v, color=col, label='X0=(%.f, %.f)' % ( X0[0], X0[1]) )

#-------------------------------------------------------
# define a grid and compute direction at each point
ymax = p.ylim(ymin=0)[1]                        # get axis limits
xmax = p.xlim(xmin=0)[1]
nb_points   = 20

x = linspace(0, xmax, nb_points)
y = linspace(0, ymax, nb_points)

X1 , Y1  = meshgrid(x, y)                       # create a grid
DX1, DY1 = dX_dt([X1, Y1])                      # compute growth rate on the gridt
M = (hypot(DX1, DY1))                           # Norm of the growth rate
M[ M == 0] = 1.                                 # Avoid zero division errors
DX1 /= M                                        # Normalize each arrows
DY1 /= M

#-------------------------------------------------------
# Drow direction fields, using matplotlib 's quiver function
# I choose to plot normalized arrows and to use colors to give information on
# the growth speed
p.title('Trajectories and direction field')
Q = p.quiver(X1, Y1, DX1, DY1, M, pivot='mid', cmap=p.cm.autumn)
p.xlabel('Number of Rabbits')
p.ylabel('Number of Foxes')
p.legend()
p.grid()
p.xlim(0, xmax)
p.ylim(0, ymax)
f2.savefig('rabbits_and_foxes_2.png')
#
#
# We can see on this graph that an intervention on fox or rabbit populations can
# have non intuitive effects. If, in order to decrease the number of rabbits,
# we introduce foxes, this can lead to an increase of rabbits in the long run,
# if that intervention happens at a bad moment.
#
#
# == Plotting contours ==
#
# We can verify that the fonction IF defined below remains constant along a trajectory:
#
def IF(X):
    u, v = X
    return u**(c/a) * v * exp( -(b/a)*(d*u+v) )

def IF2(X):
    u, v = X
    return u**(c/a) * v * exp( -(b/a)*(d*u+v) )

# We will verify that IF remains constant for differents trajectories
for v in values:
    X0 = v * X_f1                               # starting point
    X = integrate.odeint( dX_dt, X0, t)
    I = IF(X.T)                                 # compute IF along the trajectory
    I_mean = I.mean()
    delta = 100 * (I.max()-I.min())/I_mean
    print 'X0=(%2.f,%2.f) => I ~ %.1f |delta = %.3G %%' % (X0[0], X0[1], I_mean, delta)

# >>> X0=( 6, 3) => I ~ 20.8 |delta = 6.19E-05 %
#     X0=( 9, 4) => I ~ 39.4 |delta = 2.67E-05 %
#     X0=(12, 6) => I ~ 55.7 |delta = 1.82E-05 %
#     X0=(15, 8) => I ~ 66.8 |delta = 1.12E-05 %
#     X0=(18, 9) => I ~ 72.4 |delta = 4.68E-06 %
#
# Potting iso-contours of IF can be a good representation of trajectories,
# without having to integrate the ODE
#
#-------------------------------------------------------
# plot iso contours
nb_points = 80                              # grid size

x = linspace(0, xmax, nb_points)
y = linspace(0, ymax, nb_points)

X2 , Y2  = meshgrid(x, y)                   # create the grid
Z2 = IF([X2, Y2])                           # compute IF on each point

f3 = p.figure()
CS = p.contourf(X2, Y2, Z2, cmap=p.cm.Purples_r, alpha=0.5)
CS2 = p.contour(X2, Y2, Z2, colors='black', linewidths=2. )
p.clabel(CS2, inline=1, fontsize=16, fmt='%.f')
p.grid()
p.xlabel('Number of Rabbits')
p.ylabel('Number of Foxes')
p.ylim(1, ymax)
p.xlim(1, xmax)
p.title('IF contours')
f3.savefig('rabbits_and_foxes_3.png')
p.show()
#
#
# # vim: set et sts=4 sw=4:


import numpy as np
import matplotlib
import copy
np.set_printoptions(threshold=np.nan)
np.set_printoptions(precision=16)

def matgen(m,condno):
    [U,X] = np.linalg.qr(np.random.randn(m,m))
    [V,X] = np.linalg.qr(np.random.randn(m,m))
    S = np.diag(condno**((1-np.linspace(1,m,m))/(m-1)))
    return U@S@V

def exercise_1():
    ge_err,inv_err,cr_err = [],[],[]
    m = 20
    for condno in [0,4,8,12,16]:

        A = matgen(m,10**condno)
        xtrue = np.random.rand(m)
        b = A@xtrue

        x_ge = np.linalg.solve(A,b)
        ge_err.append([condno, np.linalg.norm(x_ge-xtrue)/np.linalg.norm(xtrue),
               np.linalg.norm(b-A@x_ge)/(np.linalg.norm(A)*np.linalg.norm(x_ge))])

        Ainv =  np.linalg.inv(A)
        x_inv = Ainv@b
        inv_err.append([condno, np.linalg.norm(x_inv-xtrue)/np.linalg.norm(xtrue),
               np.linalg.norm(b-A@x_inv)/(np.linalg.norm(A)*np.linalg.norm(x_inv))])

        detA = np.linalg.det(A)
        x_cr = np.zeros(m)
        for j in range(m):
            A_j = copy.deepcopy(A)
            A_j[:,j] = b
            x_cr[j] = np.linalg.det(A_j)/detA
        cr_err.append([condno, np.linalg.norm(x_cr-xtrue)/np.linalg.norm(xtrue),
               np.linalg.norm(b-A@x_cr)/(np.linalg.norm(A)*np.linalg.norm(x_cr))])

    return [ge_err,inv_err,cr_err]

def exercise_2():
    m = 60
    A = np.tril(np.full((m,m),-1),-1)+np.identity(m)
    A[:,m-1] = np.full(m,1)

    x = np.random.randn(m,1)
    b = A@x

    x_ge = np.linalg.solve(A,b)

    [Q,R] = np.linalg.qr(A)
    x_qr = np.linalg.solve(R,Q.T@b)

#    plt.scatter(np.log10(x-x_ge),range(m))
    return [np.linalg.cond(A,2),np.linalg.norm(x-x_ge,2),np.linalg.norm(x-x_qr,2)]


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

# # Vector manipulation in Python
#
# In this lab, you will have the opportunity to practice once again with the NumPy library. This time, we will explore some advanced operations with arrays and matrices.
#
# At the end of the previous module, we used PCA to transform a set of many variables into a set of only two uncorrelated variables. This process was made through a transformation of the data called rotation.
#
# In this week's assignment, you will need to find a transformation matrix from English to French vector space embeddings. Such a transformation matrix is nothing else but a matrix that rotates and scales vector spaces.
#
# In this notebook, we will explain in detail the rotation transformation.

# ## Transforming vectors
#
# There are three main vector transformations:
# * Scaling
# * Translation
# * Rotation
#
# In previous notebooks, we have applied the first two kinds of transformations. Now, let us learn how to use a fundamental transformation on vectors called _rotation_.
#
# The rotation operation changes the direction of a vector, letting unaffected its dimensionality and its norm. Let us explain with some examples.
#
# In the following cells, we will define a NumPy matrix and a NumPy array. Soon we will explain how this is related to matrix rotation.

# In[1]:

import numpy as np                     # Import numpy for array manipulation
import matplotlib.pyplot as plt        # Import matplotlib for charts
from utils_nb import plot_vectors      # Function to plot vectors (arrows)

# ### Example 1

# In[2]:

# Create a 2 x 2 matrix
R = np.array([[2, 0],
              [0, -2]])

# In[3]:

x = np.array([[1, 1]]) # Create a 1 x 2 matrix

# The dot product between a vector and a square matrix produces a rotation and a scaling of the original vector.
#
# Remember that our recommended way to get the dot product in Python is np.dot(a, b):

# In[4]:

y = np.dot(x, R) # Apply the dot product between x and R
y

# We are going to use Pyplot to inspect the effect of the rotation on 2D vectors visually. For that, we have created a function `plot_vectors()` that takes care of all the intricate parts of the visual formatting. The code for this function is inside the `utils_nb.py` file.
#
# Now we can plot the vector $\vec x = [1, 1]$ in a cartesian plane. The cartesian plane will be centered at `[0,0]` and its x and y limits will be between `[-4, +4]`

# In[5]:

plot_vectors([x], axes=[4, 4], fname='transform_x.svg')

# Now, let's plot in the same system our vector $\vec x = [1, 1]$ and its dot product with the matrix
#
# $$Ro = \begin{bmatrix} 2 & 0 \\ 0 & -2 \end{bmatrix}$$
#
# $$y = x \cdot Ro = [[2, -2]]$$

# In[6]:

plot_vectors([x, y], axes=[4, 4], fname='transformx_and_y.svg')

# Note that the output vector `y` (blue) is transformed in another vector.

# ### Example 2
#
# We are going to use Pyplot to inspect the effect of the rotation on 2D vectors visually. For that, we have created a function that takes care of all the intricate parts of the visual formatting. The following procedure plots an arrow within a Pyplot canvas.
#
# Data that is composed of 2 real attributes is telling to belong to a $ RxR $ or $ R^2 $ space. Rotation matrices in $R^2$ rotate a given vector $\vec x$ by a counterclockwise angle $\theta$ in a fixed coordinate system. Rotation matrices are of the form:
#
# $$Ro = \begin{bmatrix} cos \theta & -sin \theta \\ sin \theta & cos \theta \end{bmatrix}$$
#
# **(Note:** This notebook uses $$y = x \cdot Ro$$ But if you use $$y = Ro \cdot x.T$$
#
# Then the rotation matrices in $R^2$ rotate a given vector $\vec x$ by a clockwise angle $\theta$ in a fixed coordinate system.**)**
#
# The trigonometric functions in Numpy require the angle in radians, not in degrees. In the next cell, we define a rotation matrix that rotates vectors by $100^o$.

# In[7]:

angle = 100 * (np.pi / 180) #convert degrees to radians

Ro = np.array([[np.cos(angle), -np.sin(angle)],
              [np.sin(angle), np.cos(angle)]])

x2 = np.array([2, 2]).reshape(1, -1) # make it a row vector
y2 = np.dot(x2, Ro)

print('Rotation matrix')
print(Ro)
print('\nRotated vector')
print(y2)

print('\n x2 norm', np.linalg.norm(x2))
print('\n y2 norm', np.linalg.norm(y2))
print('\n Rotation matrix norm', np.linalg.norm(Ro))

# In[8]:

plot_vectors([x2, y2], fname='transform_02.svg')

# Some points to note:
#
# * The norm of the input vector is the same as the norm of the output vector. Rotations matrices do not modify the norm of the vector, only its direction.
# * The norm of any $R^2$ rotation matrix is always $\sqrt 2 = 1.414221$

# ## Frobenius Norm
#
# The Frobenius norm is the generalization to $R^2$ of the already known norm function for vectors
#
# $$\| \vec a \| = \sqrt {{\vec a} \cdot {\vec a}} $$
#
# For a given $R^2$ matrix A, the frobenius norm is defined as:
#
# $$\|\mathrm{A}\|_{F} \equiv \sqrt{\sum_{i=1}^{m} \sum_{j=1}^{n}\left|a_{i j}\right|^{2}}$$
#

# In[9]:

A = np.array([[2, 2],
              [2, 2]])

# `np.square()` is a way to square each element of a matrix. It must be equivalent to use the * operator in Numpy arrays.

# In[10]:

A_squared = np.square(A)
A_squared

# Now you can sum over the elements of the resulting array, and then get the square root of the sum.

# In[11]:

A_Frobenius = np.sqrt(np.sum(A_squared))
A_Frobenius

# That was the extended version of the `np.linalg.norm()` function. You can check that it yields the same result.

# In[12]:

print('Frobenius norm of the Rotation matrix')
print(np.sqrt(np.sum(Ro * Ro)), '== ', np.linalg.norm(Ro))


# -*- coding: utf-8 -*-
"""
Created on Fri Oct  1 21:39:53 2021

@author: Oliver
"""
import matplotlib.pyplot as plt
import numpy as np
import timeit

x=np.linspace(-10,10,50)
f =  x**2 + 4*x - 12
function = lambda x: x**2 + 4*x - 12
plt.plot(x,f,'g')
input_a =  int(input("Please give value of a: "))
input_b =  int(input("Please give value of b: "))

def bisection(f,a,b,N):
    if function(a)*function(b) >= 0:
        print("Bisection method fails.")
        return None
    a_n = a
    b_n = b
    for n in range(1,N+1):
        m_n = (a_n + b_n)/2
        f_m_n = function(m_n)
        if function(a_n)*f_m_n < 0:
                a_n = a_n
                b_n = m_n
        elif function(b_n)*f_m_n < 0:
                a_n = m_n
                b_n = b_n
        elif f_m_n == 0:
            print(f"Found exact solution after {n} tries")
            return m_n
        else:
            print("Bisection method fails.")
            return None
    return (a_n + b_n)/2

start = timeit.default_timer()
approx_phi = bisection(f,input_a,input_b,25)
stop = timeit.default_timer()
print('Time of original bisection without  error: ', stop - start)
print(f'The zero is at: {approx_phi}')


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

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

# We want to adjust the next function
#y = B + C cos(x) + D sin(x) + E cos(2x) + F sin(2x) + G cos(3x) + H sin(3x)

points = np.array([[-4,-1],[-3,0],[-2,-1.5],[-1,0.5],[0,1],[1,-1],[2,-0.5,],[3,2],[4,-1]])

points_x = points[:,0]
points_y = points[:,1]
cos_x  = np.cos(points_x)
sin_x  = np.sin(points_x)
cos_2x = np.cos(2*points_x)
sin_2x = np.sin(2*points_x)
cos_3x = np.cos(3*points_x)
sin_3x = np.sin(3*points_x)

n = points.shape[0]
yy = points_y
XX = np.vstack([np.ones(n),cos_x,sin_x,cos_2x,sin_2x,cos_3x,sin_3x]).T
p = XX.shape[1]

# We compute the coeff.
B, C, D, E, F, G, H = np.linalg.lstsq(XX, yy, rcond=None)[0]
params  = [B, C, D, E, F, G, H]

# Calculate the SSE
SSE = np.linalg.lstsq(XX, yy, rcond=None)[1]

# We get confidence interval
alpha = 0.05
x0 = np.linspace(-4.5, 4.5, 50)
X0 = np.vstack([np.ones(len(x0)),np.cos(x0),np.sin(x0),
    np.cos(2*x0),np.sin(2*x0),np.cos(3*x0),np.sin(3*x0)]).T

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

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

plt.figure(figsize=(10,5))
plt.plot(points_x, points_y, 'o', label='Original data', markersize=5)
plt.plot(x0, B+C*np.cos(x0)+D*np.sin(x0)+E*np.cos(2*x0)+F*np.sin(2*x0)+G*np.cos(3*x0)+H*np.sin(3*x0),
    'r', label='Fitted trigonometric function')
plt.fill_between(x0, low_pred, upp_pred, facecolor='green', alpha=0.5, label='Prediction interval')
plt.fill_between(x0, low_conf, upp_conf, facecolor='yellow', alpha=0.5, label='Confidence interval')
plt.legend(loc='upper left')


import numpy as np
from numpy import log, nan_to_num

class CrossEntropyCost:
    @staticmethod
    def evaluate(activation, true_label):
        """Return the cost associated with an output activation and desired output
        ``y``.

        The cross-entropy is positive number.
        Note that np.nan_to_num is used to ensure numerical
        stability.  In particular, if both ``a`` and ``y`` have a 1.0
        in the same slot, then the expression (1-y)*np.log(1-a)
        returns nan.  The np.nan_to_num ensures that that is converted
        to the correct value (0.0).

        """
        return np.sum(nan_to_num(-true_label * log(activation) - (1 - true_label) * log(1 - activation)))

    @staticmethod
    def delta(z, activation, true_label):
        """Computes the error delta from the output layer.

        Note that the  parameter ``z`` is not used by the method.
        It is included in the method's parameters in order to make the interface
        consistent with the delta method for other cost classes.
        """
        return activation - true_label

class QuadraticCost:
    @staticmethod
    def evaluate(activation, true_label):
        """Return the cost associated with an output activation and desired true label (``y``)."""
        return 0.5 * np.linalg.norm(activation - true_label) ** 2

    @staticmethod
    def delta(z, activation, true_label):
        """Computes the error delta from the output layer."""
        return (activation - true_label) * QuadraticCost.sigmoid_prime(z)

    @staticmethod
    def derivative(output_activations, y):
        r"""Return the vector of partial derivatives

        \partial C_x / \partial a for the output activations."""
        return output_activations - y


import numpy as np

# Conval
def conv2(X, k):
    x_row, x_col = X.shape
    k_row, k_col = k.shape
    ret_row, ret_col = x_row - k_row + 1, x_col - k_col + 1

    ret = np.empty((ret_row, ret_col))
    for y in range(ret_row):
        for x in range(ret_col):
            sub = X[y: y + k_row, x: x + k_col]
            ret[y, x] = np.sum(k * sub)
    return ret

def conv3(X, k):
    x_row, x_col, x_ch = X.shape
    k_row, k_col = k.shape
    ret_row, ret_col, ret_ch = x_row - k_row + 1, x_col - k_col + 1, x_ch

    ret = np.empty((ret_row, ret_col, ret_ch))
    for c in range(ret_ch):
        for y in range(ret_row):
            for x in range(ret_col):
                sub = X[y: y + k_row, x: x + k_col, c: c+1]
                ret[y, x, c] = np.sum(k * sub.reshape(k_row, k_col))
    return ret

# MAX & MEAN Pooling
def pooling_2d(X, mode=np.max, size=2):
    x_row, x_col = X.shape
    ret_row, ret_col = x_row // size, x_col // size + 1

    ret = np.empty((ret_row, ret_col))
    for i1, y in enumerate(range(0, x_row, size)):
        for i2, x in enumerate(range(0, x_col, size)):
            sub = X[y: y + size, x: x + size]
            ret[i1, i2] = mode(sub)

    return ret

def pooling_3d(X, mode=np.max, size=2):
    x_row, x_col, x_ch = X.shape
    ret_row, ret_col = x_row // size, x_col // size + 1

    ret = np.empty((ret_row, ret_col, x_ch))
    for c in range(x_ch):
        for i1, y in enumerate(range(0, x_row, size)):
            for i2, x in enumerate(range(0, x_col, size)):
                sub = X[y: y + size, x: x + size, c: c + 1]
                ret[i1, i2, c] = mode(sub)

    return ret

# add Padding
def padding_2d(X, k_size=3):
    x_row, x_col = X.shape
    pad_size = (k_size - 1) // 2

    ret = np.zeros((x_row + pad_size*2, x_col+ pad_size*2))
    ret[pad_size: x_row + pad_size, pad_size: x_col + pad_size] = X[:, :]

    return ret

def padding_3d(X, k_size=3):
    x_row, x_col, x_ch = X.shape
    pad_size = (k_size - 1) // 2

    ret = np.zeros((x_row + pad_size*2, x_col+ pad_size*2, x_ch))
    ret[pad_size: x_row + pad_size, pad_size: x_col + pad_size, :] = X[:, :, :]

    return ret


"""
Math library example
"""
import numpy as np

def euler(n):

    """Function to calculate Euler's number :math:`e` thorugh Taylor series

    .. math::

        e = 1 + \\sum_n^\\infty \\frac{1}{n!}

    Parameters
    ----------
    n : int
        Specify the order of the truncated series

    Returns
    -------
    e_value : float
        Euler number
    """

    if n < 0:
        raise ValueError("Only positive integers are allowed")
    n += 1
    e_value = 0
    for i in range(n):
        e_value += 1 / factorial(i)
    return e_value

def factorial(n):
    if n > 0:
        return n * factorial(n - 1)
    else:
        return 1

def pi(mc_points=1e7):

    """Function to calculate :math:`\pi` using Monte-Carlo

    Parameters
    ----------
    mc_points : int
        Specify the number of points for the Monte Carlo integration

    Returns
    -------
    result : float
        Estimated value of :math:`\pi`
    """
    mc_points = int(mc_points)
    x = np.random.uniform(0, 1, mc_points).reshape(-1, 2)
    area = np.sum(np.linalg.norm(x, axis=1) < 1)
    result = (area / mc_points) * 8
    return result


#!/usr/bin/env python

import numpy as np

def sigmoid(x):
    """
    Compute the sigmoid function for the input here.

    Arguments:
    x -- A scalar or numpy array.

    Return:
    s -- sigmoid(x)
    """

    ### YOUR CODE HERE
    s = 1 / (1 + np.exp(-1 * x))
    ### END YOUR CODE

    return s

def sigmoid_grad(s):
    """
    Compute the gradient for the sigmoid function here. Note that
    for this implementation, the input s should be the sigmoid
    function value of your original input x.

    Arguments:
    s -- A scalar or numpy array.

    Return:
    ds -- Your computed gradient.
    """

    ### YOUR CODE HERE
    ds = s * (1 - s)
    ### END YOUR CODE

    return ds

def test_sigmoid_basic():
    """
    Some simple tests to get you started.
    Warning: these are not exhaustive.
    """
    print "Running basic tests..."
    x = np.array([[1, 2], [-1, -2]])
    f = sigmoid(x)
    g = sigmoid_grad(f)
    print f
    f_ans = np.array([
        [0.73105858, 0.88079708],
        [0.26894142, 0.11920292]])
    assert np.allclose(f, f_ans, rtol=1e-05, atol=1e-06)
    print g
    g_ans = np.array([
        [0.19661193, 0.10499359],
        [0.19661193, 0.10499359]])
    assert np.allclose(g, g_ans, rtol=1e-05, atol=1e-06)
    print "You should verify these results by hand!\n"

def test_sigmoid():
    """
    Use this space to test your sigmoid implementation by running:
        python q2_sigmoid.py
    This function will not be called by the autograder, nor will
    your tests be graded.
    """
    print "Running your tests..."
    ### YOUR CODE HERE
    raise NotImplementedError
    ### END YOUR CODE

if __name__ == "__main__":
    test_sigmoid_basic();
    #test_sigmoid()


# coding: utf-8
import numpy as np
from cv2 import cv2
import matplotlib.pyplot as plt

# OpenCV provides the functions cv2.dft() and cv2.idft() for this. It returns the same result as previous, but with two channels. First channel will have the real part of the result and second channel will have the imaginary part of the result. The input image should be converted to np.float32 first. We will see how to do it.

img = cv2.imread(r'pictures\messi5.jpg',0)

dft = cv2.dft(np.float32(img),flags = cv2.DFT_COMPLEX_OUTPUT)
dft_shift = np.fft.fftshift(dft)

magnitude_spectrum = 20*np.log(cv2.magnitude(dft_shift[:,:,0],dft_shift[:,:,1]))

plt.subplot(121),plt.imshow(img, cmap = 'gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(magnitude_spectrum, cmap = 'gray')
plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])
plt.show()

# Note that you can also use cv2.cartToPolar() which returns both magnitude and phase in a single shot, calculates the magnitude and angle of 2D vectors.

# So, now we have to do inverse DFT. In previous session, we created a HPF, this time we will see how to remove high frequency contents in the image, ie we apply LPF to image. It actually blurs the image. For this, we create a mask first with high value (1) at low frequencies, ie we pass the LF content, and 0 at HF region.

rows, cols = img.shape
crow,ccol = rows/2 , cols/2

# create a mask first, center square is 1, remaining all zeros
mask = np.zeros((rows,cols,2),np.uint8)
mask[int(crow-30):int(crow+30), int(ccol-30):int(ccol+30)] = 1

# apply mask and inverse DFT
fshift = dft_shift*mask
f_ishift = np.fft.ifftshift(fshift)
img_back = cv2.idft(f_ishift)
img_back = cv2.magnitude(img_back[:,:,0],img_back[:,:,1])

plt.subplot(121),plt.imshow(img, cmap = 'gray')
plt.title('Input Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(img_back, cmap = 'gray')
plt.title('Magnitude Spectrum'), plt.xticks([]), plt.yticks([])
plt.show()

# As usual, OpenCV functions cv2.dft() and cv2.idft() are faster than Numpy counterparts. But Numpy functions are more user-friendly. For more details about performance issues, see below section.


#!/usr/local/bin/python
#-*- coding: utf-8 -*-
#
# Author:   kentarowada
# Mail:     www.kentaro.wada@gmail.com
# URL:      http://wkentaro.com
# Created:  2014-06-25
# Filename: my_inv.py
#
import numpy as np

def my_det(arr):
    n = len(arr)
    for i in range(n):
        for j in range(n):
            if i < j:
                tmp = arr[j][i] / arr[i][i]
                for k in range(n):
                    arr[j][k] -= arr[i][k]*tmp

    det = 1.0
    for i in range(n):
        det *= arr[i][i];
    return det

def my_inv(arr):
    arr = np.array(arr, dtype=np.float64)
    n = len(arr)
    iarr = np.identity(n)

    # 掃き出し法
    for i in range(n):
        tmp = 1 / arr[i][i]
        for j in range(n):
            arr[i][j] *= tmp
            iarr[i][j] *= tmp
        for j in range(n):
            if i != j:
                tmp = arr[j][i]
                for k in range(n):
                    arr[j][k] -= arr[i][k] * tmp
                    iarr[j][k] -= iarr[i][k] * tmp
    return iarr

def my_output_inv(arr):
    arr = np.array(arr)
    print "A-->"
    print arr

    det = my_det(arr)
    print "determinant -->",
    print det

    if int(det) == 0:
        print "--> No inverse array"
        return

    iarr = my_inv(arr)
    print "A inverse -->"
    print iarr

def main():
    arr = np.array([[1, 2],
                    [3, 4]])
    my_output_inv(arr)

    print "--"

    arr2 = np.array([[3, 2],
                     [6, 4]])
    my_output_inv(arr2)

if __name__ == '__main__':
    main()


import numpy as np
from numpy.random import default_rng

def residual_sum_of_squares(predictions, y_values):
    """
    Calculate the Residual Sum of Squares (RSS)

    The sum of the squares of the residuals and the residuals is
    the difference between the predicted output and the true output.

    Returns:
        the RSS value
    """
    # then compute the residuals (since we are squaring it doesn't matter which order you subtract)
    residuals = predictions - y_values
    # square the residuals and add them up
    return np.sum(residuals * residuals)

def predict_output(feature_matrix: np.ndarray, weights: np.ndarray) -> np.ndarray:
    """
    Predict the regression value for N input elements

    Args:
        feature_matrix: a 2D numpy matrix containing the features as columns
        weights: a 1D numpy array of the corresponding feature weights

    Returns:
        a 1D numpy array with the respective model prediction
    """
    return np.dot(feature_matrix, weights.T)

# def predict_output(feature_matrix: np.ndarray, weights: np.ndarray) -> np.ndarray:
#     """
#     Create a regression prediction vector by using dot product
#
#     Args:
#         feature_matrix: a 2D numpy array with features as columns
#         weights: a 1D numpy array of the corresponding feature weights
#
#     Returns:
#         a 1D numpy array with the respective model prediction
#     """
#     predictions = np.dot(feature_matrix, weights)
#     return predictions

def random_init(size, seed=12345678903141592653589793):
    rng = default_rng(seed)
    return rng.standard_normal(size)


from sklearn.utils import check_random_state
import numpy as np
import matplotlib.pyplot as plt

from ya_pca.utils import sample_parallel
from ya_pca.linalg_utils import svd_wrapper

def select_rank_horn(X, n_perm=1000, q=0.95, max_rank=None, svals=None,
                     random_state=None, n_jobs=None, backend=None):
    """
    Selects the PCA rank using Horn's Parallel Analysis.
    See https://arxiv.org/pdf/1710.00479.pdf.

    Parameters
    ----------
    X: array-like, (n_samples, n_features)
        The data matrix.

    n_perm: int
        Number of permutations.

    q: float
        The cutoff quantile between 0 and 1.
        Observed singular values above this null quantile are deemed to be signal.

    max_rank: None, int
        Maximum PCA rank to check.

    svals: None, array-like
        (optional) Precomputed singular values.

    random_state: None, int
        Random seed for sampling.

    n_jobs: None, int
        Parallelize the permutation samples.

    Output
    ------
    rank_est, out

    rank_est: int
        Estimated rank

    out: dict
        All output from rank selection algorithm.
    """
    # TODO: better name for n_samples
    if svals is not None:
        obs_svals = svals
    else:
        obs_svals = svd_wrapper(X, rank=max_rank)[1]

    perm_samples = sample_parallel(fun=sample_horn,
                                   kws={'X': X},
                                   # random_state=random_state,
                                   n_jobs=n_jobs)
    perm_samples = np.array(perm_samples)

    sval_cutoff = np.quantile(perm_samples, q=q)
    rank_est = sum(obs_svals > sval_cutoff)

    return rank_est, {'perm_samples': perm_samples,
                      'obs_svals': obs_svals,
                      'sval_cutoff': sval_cutoff}

def sample_horn(X, random_state=None):
    """
    Permutes each colum the computes the largest singular value.
    """
    rng = check_random_state(random_state)

    idxs = np.arange(X.shape[0])
    X_perm = np.zeros_like(X)

    for j in range(X.shape[1]):
        perm_idxs = rng.permutation(idxs)
        X_perm[:, j] = X[:, j][perm_idxs]

    return np.linalg.norm(X_perm, ord=2)

def plot_horn(obs_svals, perm_samples, sval_cutoff):
    """
    Visualization for Horn's Parallel Analysis.
    Histogram of null distribution.
    """

    plt.hist(perm_samples, color='black')
    for sval in obs_svals:
        if sval > sval_cutoff:
            ls = '-'
            # alpha = 0.5
            lw = 2
        else:
            ls = '--'
            lw = 1
            # alpha = 1
        plt.axvline(sval, color='blue', ls=ls, lw=lw)
    plt.axvline(sval_cutoff, label='Threshold: {:1.3f}'.format(sval_cutoff),
                color='red', lw=2)


import numpy as np

from typing import Tuple
from numpy.typing import ArrayLike
from liegroups.numpy import SO2, SE2, SO3, SE3
from numpy import sin, cos

def angle_to_se2(a: float, theta: float) -> SE2:
    """Transform a single set of DH parameters into an SE2 matrix
    :param a: link length
    :param theta: rotation
    :returns: SE2 matrix
    :rtype: lie.SE2Matrix
    """
    # R = SO2.from_angle(theta)  # TODO: active or passive (i.e., +/- theta?)
    R = SO2.from_angle(theta)
    return SE2(R, R.dot(np.array([a, 0.0])))  # TODO: rotate the translation or not?

def skew(x):
    """
    Creates a skew symmetric matrix from vector x
    """
    X = np.array([[0, -x[2], x[1]], [x[2], 0, -x[0]], [-x[1], x[0], 0]])
    return X

def trans_axis(t, axis="z") -> SE3:
    if axis == "z":
        return SE3(SO3.identity(), np.array([0, 0, t]))
    if axis == "y":
        return SE3(SO3.identity(), np.array([0, t, 0]))
    if axis == "x":
        return SE3(SO3.identity(), np.array([t, 0, 0]))
    raise Exception("Invalid Axis")

def rot_axis(theta, axis="z") -> SE3:
    if axis == "z":
        return SE3(SO3.rotz(theta), np.array([0, 0, 0]))
    if axis == "y":
        return SE3(SO3.roty(theta), np.array([0, 0, 0]))
    if axis == "x":
        return SE3(SO3.rotx(theta), np.array([0, 0, 0]))
    raise Exception("Invalid Axis")

def max_min_distance_revolute(r, P, C, N):
    delta = P-C
    d_min_s = N.dot(delta)**2 + (np.linalg.norm(np.cross(N, delta)) - r)**2
    if d_min_s > 0:
        d_min = np.sqrt(d_min_s)
    else:
        d_min = 0
    d_max_s = N.dot(delta)**2 + (np.linalg.norm(np.cross(N, delta)) + r)**2
    if d_max_s > 0:
        d_max = np.sqrt(d_max_s)
    else:
        d_max = 0

    return d_max, d_min

def best_fit_transform(A: ArrayLike, B: ArrayLike) -> Tuple[ArrayLike, ArrayLike]:
    """
    Calculates the least-squares best-fit transform that maps corresponding points A to B in m spatial dimensions
    Input:
      A: Nxm numpy array of corresponding points
      B: Nxm numpy array of corresponding points
    Returns:
      R: mxm rotation matrix
      t: mx1 translation vector
    """

    # try:
    assert A.shape == B.shape
    # except AssertionError:
    #     print("A: {:}".format(A))
    #     print("B: {:}".format(B))

    # get number of dimensions
    m = A.shape[1]

    # translate points to their centroids
    centroid_A = np.mean(A, axis=0)
    centroid_B = np.mean(B, axis=0)

    AA = A - centroid_A
    BB = B - centroid_B

    # rotation matrix
    H = np.dot(AA.T, BB)
    U, S, Vt = np.linalg.svd(H)
    R = np.dot(Vt.T, U.T)
    # translation
    #
    # special reflection case
    # if np.linalg.det(R) < 0:
    #     print("det(R) < R, reflection detected!, correcting for it ...\n")
    # Vt[2, :] *= -1
    # R = np.dot(Vt.T, U.T)

    t = centroid_B.T - np.dot(R, centroid_A.T)
    return R, t


#! /usr/bin/python

import sys, re
from scipy.optimize.optimize import fmin_cg, fmin_bfgs, fmin
import numpy as np
import matplotlib.pyplot as plt
from numpy import loadtxt, where, zeros, e, array, log, ones, mean, where
from pylab import scatter, show, legend, xlabel, ylabel, plot
from scipy.optimize import fmin_bfgs
import math

def sigmoid(X):
   g=1/(1+np.exp(-X))
   return g

def costFunction(theta,X,y):
   theta.shape = (1, 3)
   m = y.size
   h = sigmoid(X.dot(theta.conj().transpose()))
   first = ((-y).T.dot(log(h)))
   second = (1-y).T.dot(log(1-h))
   J =(first - second)/m
   return J.sum()

def gradFunction(theta,X,y):
   theta.shape = (1, 3)
   grad = zeros(3)
   h = sigmoid(X.dot(theta.conj().transpose()))
   delta = h - y
   l = grad.size
   for i in range(l):
      sumdelta = delta.conj().transpose().dot(X[:, i])
      grad[i] = (1.0 / m) * sumdelta * (-1)
   theta.shape = (3,)
   return grad

data = loadtxt('ex2data1.txt', delimiter=',')
X = data[:, 0:2]
y =  data[:, 2]
pos = where(y == 1)
neg = where(y == 0)
scatter(X[pos, 0], X[pos, 1], marker='o', c='b')
scatter(X[neg, 0], X[neg, 1], marker='x', c='r')
xlabel('X')
ylabel('Y')
legend(['X', 'Y'])

m, n = X.shape
y.shape = (m, 1)
i = ones(shape=(m, 3))
i[:, 1:3] = X

def learning_parameters(i, y):
    def f(theta):
        return costFunction(theta, i, y)

    def fprime(theta):
        return gradFunction(theta, i, y)
    theta = zeros(3)
    return fmin_bfgs(f, theta, fprime, disp=True, maxiter=400)

learning_parameters(i, y)
theta = [-25.161272, 0.206233, 0.201470]

plot_x = array([min(i[:, 1]) - 2, max(i[:, 2]) + 2])
plot_y = (-1/theta[2]) * (theta[1] * plot_x + theta[0])

plot(plot_x, plot_y)
legend(['Decision', 'Admitted', 'Not-Admitted'])
show()

prob = sigmoid(array([1.0, 45.0, 85.0]).dot(array(theta).conj().transpose()))
print 'Probability: %f' % prob

def predict(theta,X):
   m, n = X.shape
   p = zeros(shape=(m, 1))
   h = sigmoid(X.dot(theta.conj().transpose()))

   for i in range(0, h.shape[0]):
        if h[i] > 0.5:
            p[i, 0] = 1
        else:
            p[i, 0] = 0
   return p

p = predict(array(theta), i)
print "Train Accuracy:",((y[where(p == y)].size / float(y.size)) * 100.0)


"""Exercise 1"""

import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
from scipy.signal import butter, lfilter
from scipy import fftpack

def gaussian(x, mu, sigma, A):
    return A*np.exp(-(x - mu)**2/(2*sigma**2))

sample_rate = 30
T = 5
t = np.linspace(0, T, T*sample_rate, endpoint=False)
y = gaussian(t, 3.1, 0.2, 3) + np.sin(1.2*2*np.pi*t) + 1.5*np.cos(9*2*np.pi*t)
plt.plot(t, y)

z = fftpack.rfft(y)
f = fftpack.rfftfreq(len(t), t[1] - t[0])

maxima = f[np.abs(z)**2 > 2100]
print("Noise frequencies:", maxima)

plt.figure(1)
plt.plot(f, np.abs(z)**2)
plt.xlabel('f / Hz')
for freq in maxima:
    plt.axvline(x=freq, color='black', alpha=0.3, lw=5)
plt.title('Discovery of Noise Frequencies')

def bandstop_filter(data, freq_window, fs, order=5):
    nyquist_frequency = fs/2
    freq_window = np.array(freq_window)
    normal_freq = freq_window/nyquist_frequency
    b, a = butter(order, normal_freq, btype='bandstop')
    y = lfilter(b, a, data)
    return y

plt.figure(2)
sample_rate = (len(t) - 1)/(t[-1])
y_filt = bandstop_filter(y, [1.15, 1.25], sample_rate)
y_filt = bandstop_filter(y_filt, [8.9, 9.1], sample_rate)
plt.plot(t, y_filt)
plt.title('Data after bandstop filtering')

params, __ = curve_fit(gaussian, t, y_filt)
print("Gaussian paramaters:", params)

plt.figure(3)
plt.plot(t, gaussian(t, *params))
plt.plot(t, y_filt)
plt.title('Filtered data fit with Gaussian');

"""Exercise 2"""

from scipy.special import eval_legendre
from scipy.integrate import quad

def f(x):
    return np.sin(np.pi*x)

def a(n):
    g = lambda x: f(x)*eval_legendre(n, x)
    integral = quad(g, -1, 1)[0]
    return (2*n + 1)/2 * integral

# first few a_n coefficients up to n = 5
print("Coefficients:", [a(n) for n in range(5+1)])

def legendre_series(x, N):
    y = np.zeros(len(x))
    for n in range(N+1):
        y += a(n)*eval_legendre(n, x)
    return y

x = np.linspace(-1, 1, 100)
plt.plot(x, f(x), label=r'$\sin(nx)$')
plt.plot(x, legendre_series(x, 5), label=r'$\sum_{n=0}^{5} a_n P_n(x)$')
plt.legend(loc='best');


import numpy as np
import polyFit
import scipy
from scipy import interpolate
import matplotlib.pyplot as plt

h=[0.0,1.525,3.050,4.575,6.1,7.625,9.15] #x values
den=[1,0.8617,0.7385,0.6292,0.5328,0.4481,0.3741] #y values
hrang=np.linspace(0,9.15,100)

print 'Using Polynomial Interpolation: ', '\n'

l_001=interpolate.barycentric_interpolate(h,den,(2,5)) #Using interpolate from scipy. Uses barycentric polynomial interpolation. Arguments: (x values, y values, points at which you wish to evaluate)

print 'At 2km the density of air will be ', l_001[0]

print 'At 5km the density of air will be ', l_001[1]

###
print '\n', 'Using Cubic Splines: ', '\n'

l_002=interpolate.interp1d(h,den,kind='cubic') #Interpolatioon from scipy. Uses cubic splines. Arguments: (x values, y values, order of splines)

print 'At 2km the density of air will be ', l_002(2) #Calls for interpolation to be evaluated at argument

print 'At 5km the density of air will be ', l_002(5)

###

print '\n', 'Using Least Squares Fit: ', '\n'

l=polyFit.polyFit(h,den,2) #Using polyFit module to generate a list of coefficients. Arguments: (x values, y values, degree of polynomial)

def l_003(x): #defining a function for the polynomial generated by polyFit
	l_003=l[0]+l[1]*x+l[2]*x**2
	return l_003

print 'At 2km the density of air will be ', l_003(2) #using function as defined above

print 'At 5km the density of air will be ', l_003(5)

###

denl_001=interpolate.barycentric_interpolate(h,den,hrang)
denl_002=l_002(hrang)
denl_003=l_003(hrang)

plt.figure(1)
plt.plot(hrang,denl_001,'r-',2,interpolate.barycentric_interpolate(h,den,2),'bo',5,interpolate.barycentric_interpolate(h,den,5),'bo')
plt.axis([0,10,0.2,1])
plt.xlabel('Height (km)')
plt.ylabel('Air Density')
plt.title('Barycentric Interpolation')
plt.show()

plt.figure(2)
plt.plot(hrang,denl_002,'r-',2,l_002(2),'bo',5,l_002(5),'bo')
plt.axis([0,10,0.2,1])
plt.xlabel('Height (km)')
plt.ylabel('Air Density')
plt.title('Cubic Splines')
plt.show()

plt.figure(3)
plt.plot(hrang,denl_003,'r-',2,l_003(2),'bo',5,l_003(5),'bo')
plt.axis([0,10,0.2,1])
plt.xlabel('Height (km)')
plt.ylabel('Air Density')
plt.title('Least Squares Fit')
plt.show()

plt.figure(4)
plt.plot(h,den,'ro')
plt.axis([0,10,0.2,1])
plt.xlabel('Height (km)')
plt.ylabel('Air Density')
plt.title('Original Data')
plt.show()

ExamPrep/04 Curve Fitting & Interpolation/shigInterp.py


# Accepts a filename containing numeric values in each line of which the statistics need to be calculated.
# Alternately as second argument, the bucket size can also be passed.
import sys
import numpy as np

fileName = sys.argv[1]
# find median of bucket splits of data
buckets = 5

if len(sys.argv) == 3:
    # Assuming the 2nd argument is the bucket size
    # if it exists
    buckets = int(sys.argv[2])

data = np.fromfile(fileName,sep="\n")
nmap = len(data) # Number of hashes used.
print("(mean of {} hashes) = {}".format(nmap,np.mean(data)))

# Finding mean of medians and vice-versa now
idxes = np.arange(nmap)
np.random.shuffle(idxes)
# numpy.array_split allows unequal splits of data
groups = np.array_split(idxes, buckets)

mean_of_medians = np.mean([np.median(data[group_idxs]) for group_idxs in groups])
median_of_means = np.median([np.mean(data[group_idxs]) for group_idxs in groups])
print("mean of medians (from {} buckets of data) : {}".format(buckets, mean_of_medians))
print("median of means (from {} buckets of data) : {}".format(buckets, median_of_means))
print("Standard Deviation : {}".format(np.std(data)))


import numpy as np

def f1(x, y, z):
    res = x + 3 * y + 2 * z
    return res, res == 5

def f2(x, y, z):
    res = 2 * x + -y + -z
    return res, res == 1

def f3(x, y, z):
    res = -x + 2 * y + z
    return res, res == 3

x = 0.75
y = 3.25
z = -2.75

print(f1(x, y, z))
print(f2(x, y, z))
print(f3(x, y, z))

b = np.array([5, 1, 3])
A = np.array([
    [1, 3, 2],
    [2, -1, -1],
    [-1, 2, 1]
])

sol2 = np.linalg.solve(A, b)
print(sol2)
print(A.dot(sol2))

# Ax = b
# inv(A)x = inv(A)b
# x = inv(A)b

print(np.linalg.inv(A).dot(b))

A2 = np.array([
    [1, 3, 2],
    [0, 3, 1],
    [0, 0, -4]
])

B2 = np.array([5,7,11])

print(np.linalg.solve(A2, B2))


## module jacobi
''' lam,x = jacobi(a,tol = 1.0e-8).
    Solution of std. eigenvalue problem [a]{x} = lam{x}
    by Jacobi's method. Returns eigenvalues in vector {lam}
    and the eigenvectors as columns of matrix [x].
'''
import numpy as np
import math

def jacobi(a,tol = 1.0e-8): # Jacobi method

    def threshold(a):
        sum = 0.0
        for i in range(n-1):
            for j in range (i+1,n):
                sum = sum + abs(a[i,j])
        return 0.5*sum/n/(n-1)

    def rotate(a,p,k,l): # Rotate to make a[k,l] = 0
        aDiff = a[l,l] - a[k,k]
        if abs(a[k,l]) < abs(aDiff)*1.0e-36: t = a[k,l]/aDiff
        else:
            phi = aDiff/(2.0*a[k,l])
            t = 1.0/(abs(phi) + math.sqrt(phi**2 + 1.0))
            if phi < 0.0: t = -t
        c = 1.0/math.sqrt(t**2 + 1.0); s = t*c
        tau = s/(1.0 + c)
        temp = a[k,l]
        a[k,l] = 0.0
        a[k,k] = a[k,k] - t*temp
        a[l,l] = a[l,l] + t*temp
        for i in range(k):      # Case of i < k
            temp = a[i,k]
            a[i,k] = temp - s*(a[i,l] + tau*temp)
            a[i,l] = a[i,l] + s*(temp - tau*a[i,l])
        for i in range(k+1,l):  # Case of k < i < l
            temp = a[k,i]
            a[k,i] = temp - s*(a[i,l] + tau*a[k,i])
            a[i,l] = a[i,l] + s*(temp - tau*a[i,l])
        for i in range(l+1,n):  # Case of i > l
            temp = a[k,i]
            a[k,i] = temp - s*(a[l,i] + tau*temp)
            a[l,i] = a[l,i] + s*(temp - tau*a[l,i])
        for i in range(n):      # Update transformation matrix
            temp = p[i,k]
            p[i,k] = temp - s*(p[i,l] + tau*p[i,k])
            p[i,l] = p[i,l] + s*(temp - tau*p[i,l])

    n = len(a)
    p = np.identity(n,float)
    for k in range(20):
        mu = threshold(a)       # Compute new threshold
        for i in range(n-1):    # Sweep through matrix
            for j in range(i+1,n):
                if abs(a[i,j]) >= mu:
                    rotate(a,p,i,j)
        if mu <= tol: return np.diagonal(a),p
    print('Jacobi method did not converge')


from __future__ import division
import numpy as np
from scipy.sparse import spdiags
from scipy.sparse.linalg import spsolve, cg

def general_secondorder_ode_fd(func,a1,a2,a3,a=0.,b=1.,alpha=1.,beta=3.,N=5):
	# A Simple Finite Difference Scheme to solve BVP's of the form
	# a1(x)u''(x) + a2(x)u'(x) + a3(x)u(x) = f(x), x \in [a,b]
	# u(a) = alpha
	# u(b) = beta
	# (Dirichlet boundary conditions)
	#
	# U_0 = alpha, U_1, U_2, ..., U_m, U_{m+1} = beta
	# We use m+1 subintervals, giving m algebraic equations
    m = N-1
    h = (b-a)/(m+1.)         # Here we form the diagonals
    D0,Dp,Dm,diags = np.zeros((1,m)), np.zeros((1,m)), np.zeros((1,m)), np.array([0,-1,1])
    for j in range(1,D0.shape[1]):
		xj = a + (j)*h
		D0[0,j]   = h**2.*a3(xj)-2.*a1(xj)
		Dp[0,j]   = a1(xj)-h*a2(xj)/2.
		Dm[0,j-1] = a1(xj)+h*a2(xj)/2.
    # xj = a + 1.*h
    # D0[0,0] = h**2.*a3(xj)-2.*a1(xj)

    # Here we create the matrix A
    data = np.concatenate((D0,Dm,Dp),axis=0) # This stacks up rows
    A=h**(-2.)*spdiags(data,diags,m,m).asformat('csr')

	# Here we create the vector B
    B = np.zeros(m+2)
    for j in range(2,m):
        B[j] = func(a + j*h)
    xj = a+1.*h
    B[0], B[1] = alpha, func(xj)-alpha *( a1(xj)*h**(-2.) + a2(xj)*h**(-1)/2. )
    xj = a+m*h
    B[-1], B[-2]  = beta, func(xj)-beta*( a1(xj)*h**(-2.) - a2(xj)*h**(-1)/2. )

    # Here we solve the equation AX = B and return the result
    B[1:-1] = spsolve(A,B[1:-1])
    return np.linspace(a,b,m+2), B

# def general_secondorder_ode_fd(func,a1,a2,a3,a=0.,b=1.,alpha=1.,beta=3.,N=5):
# 	# A Simple Finite Difference Scheme to solve BVP's of the form
# 	# a1(x)u''(x) + a2(x)u'(x) + a3(x)u(x) = f(x), x \in [a,b]
# 	# u(a) = alpha
# 	# u(b) = beta
# 	# (Dirichlet boundary conditions)
# 	#
# 	# U_0 = alpha, U_1, U_2, ..., U_m, U_{m+1} = beta
# 	# We use m+1 subintervals, giving m algebraic equations
#     m = N-1
#     h = (b-a)/(m+1.)         # Here we form the diagonals
#     D0,D1,D2,diags = np.zeros((1,m)), np.zeros((1,m)), np.zeros((1,m)), np.array([0,-1,1])
#     for j in range(1,D1.shape[1]):
# 		xj = a + (j+1)*h
# 		D0[0,j] = h**2.*a3(xj)-2.*a1(xj)
# 		D1[0,j] = a1(xj)+h*a2(xj)/2.
# 		D2[0,j-1] = a1(xj)-h*a2(xj)/2.
#     xj = a + 1.*h
#     D0[0,0] = h**2.*a3(xj)-2.*a1(xj)
#
#     # Here we create the matrix A
#     data = np.concatenate((D0,D2,D1),axis=0) # This stacks up rows
#     A=h**(-2.)*spdiags(data,diags,m,m).asformat('csr')
#
# 	# Here we create the vector B
#     B = np.zeros(m+2)
#     for j in range(2,m):
#         B[j] = func(a + j*h)
#     xj = a+1.*h
#     B[0], B[1] = alpha, func(xj)-alpha *( a1(xj)*h**(-2.) - a2(xj)*h**(-1)/2. )
#     xj = a+m*h
#     B[-1], B[-2]  = beta, func(xj)-beta*( a1(xj)*h**(-2.) + a2(xj)*h**(-1)/2. )
#
#     # Here we solve the equation AX = B and return the result
#     B[1:-1] = spsolve(A,B[1:-1])
#     return np.linspace(a,b,m+2), B
#