from sympy import Symbol, Derivative
from sympy.solvers import solve

x = Symbol('x')
y = Symbol('y')
h = Symbol('h')

#f = 2*x**2 - y + 3*x*y
#values = (2,3)

f = 3*x**2 - 2*y + x*y
values = (2,1)

def printline(): print('---------------------------------------------------------------------------------------')

def steep_step(f, values, x, y, h):
    (xi, yi) = values
    dfdx = Derivative(f,x).doit().evalf(subs = {x:xi, y:yi})
    dfdy = Derivative(f,y).doit().evalf(subs = {x:xi, y:yi})
    xnew = xi + dfdx*h
    ynew = yi + dfdy*h
    g = f.subs(x, xnew)
    g = g.subs(y,ynew)
    dgdh = Derivative(g,h).doit()
    H = solve(dgdh, h)[0]
    xnew = xi + dfdx*H
    ynew = yi + dfdy*H
    return (xnew, ynew)

def steep_step_verbose(f, values, x, y, h):
    (xi, yi) = values
    dfdx = Derivative(f,x).doit()
    print('df/dx: ' + str(dfdx))
    dfdx = dfdx.evalf(subs = {x:xi, y:yi})
    print('df/dx @ ' + str(values) + ': ' + str(dfdx))
    dfdy = Derivative(f,y).doit()
    print('df/dy: ' + str(dfdy))
    dfdy = dfdy.evalf(subs = {x:xi, y:yi})
    print('df/dy @ ' + str(values) + ': ' + str(dfdy))
    xnew = xi + dfdx*h
    print('x = ' + str(xnew))
    ynew = yi + dfdy*h
    print('y = ' + str(ynew))
    g = f.subs(x, xnew)
    g = g.subs(y,ynew)
    print('g(h) = ' + str(g))
    dgdh = Derivative(g,h).doit()
    print("g'(h) = " + str(dgdh))
    H = solve(dgdh, h)
    print('Solutions of h: ' + str(len(H)))
    H = H[0]
    print('h* = ' + str(H))
    xnew = xi + dfdx*H
    ynew = yi + dfdy*H
    print('(x,y) = ' + str((xnew, ynew)))
    return (xnew, ynew)

printline()
print('Iteration 1: ')
values = steep_step_verbose(f, values, x, y, h)
printline()
print('Iteration 2: ')
values = steep_step_verbose(f, values, x, y, h)
(xi, yi) = values
Y = f.evalf(subs = {x:xi, y:yi})
print('Height on the mountain: ' + str(Y))
printline()


import numpy as np

def Build(type_str="sigmoid"):
    """
    Factory method that builds the specified activation function.
    """
    if (type_str == "sigmoid"):
        return SigmoidAF()
    elif (type_str == "arctan"):
        return ArctanAF()
    else:
        raise NotImplementedError("Unsupported activation function: '%s'" % (type_str))

class ActivationFunctionBaseClass:
    """
    Base class that defines the interfaces of all activation functions.
    """
    def __init__(self):
        pass

    def GetValue(self, x):
        raise NotImplementedError("Must implement GetValue().")

    def GetDerivative(self, x):
        raise NotImplementedError("Must implement GetDerivative().")

class SigmoidAF(ActivationFunctionBaseClass):
    def __init__(self):
        pass

    def GetValue(self, x):
        return 1.0 / (1.0 + np.exp(-x))

    def GetDerivative(self, x):
        v = self.GetValue(x)
        #return np.multiply(v, (1.0 - v))
        return v * (1.0 - v)

class ArctanAF(ActivationFunctionBaseClass):
    def __init__(self):
        pass

    def GetValue(self, x):
        return np.arctan(x);

    def GetDerivative(self, x):
        return 1.0 / (1.0 + np.multiply(x, x))


import numpy as np

def median_bins(values, B):
  #main variables (returns)
  mean = np.mean(values)
  stdev = np.std(values)
  bin_counts = np.zeros((B,)) # init with zeroes - , dtype=np.int
  n_smaller = 0

  #aux variables
  width = 2*stdev / B
  minval = mean-stdev

  for value in values: # for all the values in the array
    binmax = minval

    if value < minval : #skip this value
      n_smaller += 1
    else: # fit into a bin
      for index in range(B):
        binmax += width
        if value < binmax: #values > maxval -> ignored
          bin_counts[index] += 1
          break
  return (mean, stdev, n_smaller, bin_counts)

def median_approx(values, B):
  median_bins_result = median_bins(values, B)

  #resuts of bin calculation
  mean = median_bins_result[0]
  stdev = median_bins_result[1]
  n_smaller = median_bins_result[2]
  bins = median_bins_result[3]

  #other aux calculations
  minval = mean - stdev
  target_total = (len(values)+1)/2
  width = 2*stdev / B
  running_total = n_smaller

  #print("minval:", minval, "width:", width, ", running_total/n_smaller: ", running_total)

  for index in range(len(bins)): #go over every bin
     running_total += bins[index]
     #print("idx: ", index, "rt: ", running_total, ", target_total: ", target_total)
     if running_total >= target_total:
        return minval + width/2 + index*width
  return minval + width/2 + index*width

# You can use this to test your functions.
# Any code inside this `if` statement will be ignored by the automarker.
if __name__ == '__main__':
  # Run your functions with the first example in the question.
  print(median_bins([1, 1, 3, 2, 2, 6], 3))
  print(median_approx([1, 1, 3, 2, 2, 6], 3)) #2.5

  # Run your functions with the second example in the question.
  print(median_bins([1, 5, 7, 7, 3, 6, 1, 1], 4))
  print(median_approx([1, 5, 7, 7, 3, 6, 1, 1], 4)) #4.50544503131

  #3rd case
  print(median_bins([0, 1], 5))
  print(median_approx([0, 1], 5)) #0.9

  # Pathological case
  print(median_bins([1, 1, 1000], 5))
  print(median_approx([1, 1, 1000], 5)) #-42.7464930162


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

  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

bsm_call_value(S0=10,K=10,T=3./12,r=0.01,sigma=0.1)

# Vega function
def bsm_vega(S0, K, T, r, sigma):
  # Vega of European option in BSM model.
  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.norm.cdf(d1, 0.0, 1.0) * sqrt(T)
  return vega

bsm_vega(10,10,3./12,0.01,0.1)

# Implied volatility function
def bsm_call_imp_vol(S0, K, T, r, C0, sigma_est, it=100):
  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

bsm_call_imp_vol(S0=10,K=10,T=3./12,r=0.01,C0=0.3,sigma_est=0.05,it=1000)

import pandas as pd
import os
os.getcwd()

filename = 'vstoxx_data_31032014.h5'

with pd.HDFStore(filename,  mode='r') as h5:
  futures_data = h5.select('futures_data')

with pd.HDFStore(filename,  mode='r') as h5:
  options_data = h5.select('options_data')

#==============================================================================
# futures_data = pd.read_hdf(filename, 'futures_data')
# options_data= pd.read_hdf(filename, 'options_data')
#
# h5 = pd.HDFStore('vstoxx_data_31032014.h5', 'r')
# futures_data = h5['futures_data'] # VSTOXX futures data
# options_data = h5['options_data'] # VSTOXX call option data
#
#==============================================================================

h5.close()

options_data.info()
options_data.head()
futures_data.head()
options_data[['DATE', 'MATURITY', 'TTM', 'STRIKE', 'PRICE']].head()

options_data['IMP_VOL'] = 0.0

V0 = 17.6639
r = 0.01
tol = 0.5 # tolerance level for moneyness

for option in options_data.index:
  # iterating over all option quotes
  forward = futures_data[futures_data['MATURITY'] == \
            options_data.loc[option]['MATURITY']]['PRICE'].values[0]
  # picking the right futures value
  if (forward * (1 - tol) < options_data.loc[option]['STRIKE'] < forward * (1 + tol)):
      # only for options with moneyness within tolerance
      imp_vol = bsm_call_imp_vol(V0, # VSTOXX value
                                 options_data.loc[option]['STRIKE'],
                                 options_data.loc[option]['TTM'],
                                 r, # short rate
                                 options_data.loc[option]['PRICE'],
                                 sigma_est=2., # estimate for implied volatility
                                 it=100)
      options_data['IMP_VOL'].loc[option] = imp_vol

futures_data['MATURITY']
options_data.loc[46170]
options_data.loc[46170]['STRIKE']

maturities = sorted(set(options_data['MATURITY']))
maturities

plot_data = options_data[options_data['IMP_VOL'] > 0]

#iterates over all maturities and does the plotting
import matplotlib.pyplot as plt
%matplotlib inline

plt.figure(figsize=(16, 12))
for maturity in maturities:
  data = plot_data[options_data.MATURITY == maturity]
  # select data for this maturity
  plt.plot(data['STRIKE'], data['IMP_VOL'],label=maturity.date(), lw=1.5)
  plt.plot(data['STRIKE'], data['IMP_VOL'], 'r.')

plt.grid(True)
plt.xlabel('strike')
plt.ylabel('implied volatility of VSTOXX')
plt.legend()
plt.show()

keep = ['PRICE', 'IMP_VOL']
group_data = plot_data.groupby(['MATURITY', 'STRIKE'])[keep]
group_data

# any aggregation since one element in every group
group_data = group_data.sum()
group_data.head(20)
# check attributes and methods of unknown objects
dir(group_data)
#unique MATURITY and STRIKE
group_data.index.levels


"""
Contains various functions for computing statistics over 3D volumes
"""
import numpy as np

def Dice3d(a, b):
    """
    This will compute the Dice Similarity coefficient for two 3-dimensional volumes
    Volumes are expected to be of the same size. We are expecting binary masks -
    0's are treated as background and anything else is counted as data

    Arguments:
        a {Numpy array} -- 3D array with first volume
        b {Numpy array} -- 3D array with second volume

    Returns:
        float
    """
    if len(a.shape) != 3 or len(b.shape) != 3:
        raise Exception(f"Expecting 3 dimensional inputs, got {a.shape} and {b.shape}")

    if a.shape != b.shape:
        raise Exception(f"Expecting inputs of the same shape, got {a.shape} and {b.shape}")

    # TASK: Write implementation of Dice3D. If you completed exercises in the lessons
    # you should already have it.

    # From slides (and exericse)
    # Dice = 2 * intersection(x, y) / sum(x, y)
    # Where
    # Intersection = np.sum(a*b)
    # Note additional logic for scenario where denominator == 0

    # Convert to binary: here, we're not going to make a distinction between classes beyond "0" and "not 0"
    a, b = np.where(a > 0, 1, 0), np.where(b > 0, 1, 0)

    if (np.sum(a) + np.sum(b)) == 0:
        return -1

    return (np.sum(a * b) * 2.0) / (np.sum(a) + np.sum(b))

def Jaccard3d(a, b):
    """
    This will compute the Jaccard Similarity coefficient for two 3-dimensional volumes
    Volumes are expected to be of the same size. We are expecting binary masks -
    0's are treated as background and anything else is counted as data

    Arguments:
        a {Numpy array} -- 3D array with first volume
        b {Numpy array} -- 3D array with second volume

    Returns:
        float
    """
    if len(a.shape) != 3 or len(b.shape) != 3:
        raise Exception(f"Expecting 3 dimensional inputs, got {a.shape} and {b.shape}")

    if a.shape != b.shape:
        raise Exception(f"Expecting inputs of the same shape, got {a.shape} and {b.shape}")

    # TASK: Write implementation of Jaccard similarity coefficient. Please do not use
    # the Dice3D function from above to do the computation ;)
    # <YOUR CODE GOES HERE>

    # From slides (and exericse)
    # Jaccard = intersection(x, y) / union(x, y)
    # Where
    # Union = sum - intersection
    # TODO remove Similar logic for denominator == 0
    a, b = np.where(a > 0, 1, 0), np.where(b > 0, 1, 0)

    if ((np.sum(a) + np.sum(b)) - np.sum(a * b)) == 0:
        return -1

    return  np.sum(a * b) / ((np.sum(a) + np.sum(b)) - np.sum(a * b))


### Univariate batch (standard) gradient descent algorithm

### author: Dr. Marko Mitic
### year 2015
### contact: miticm@gmail.com

import numpy as np
import matplotlib.pyplot as plt

class BatchGD: #Main class for Univariate Batch Gradient Descent

    def __init__(self, data):
        ### data is given in two-column format, first column is input, second column is output
        self.x=data[:,0]
        self.y=data[:,1]
        self.m=len(data[:,0])

    def plotdata(self):
        ###
        plt.figure()
        plt.plot(self.x, self.y, 'ro')
        plt.show()

    def hypothesis(self, theta0, theta1):
        "Return univariate hypothesis"
        self.t0=theta0
        self.t1=theta1
        self.hy=self.t0+self.t1*self.x ##current hypothesis
        return self.hy

    def cost_function(self):
        "Return Cost function for hypothesis hy(of input x) and output y"
        self.J=(1./(2.*self.m))*sum((self.hy-self.y)**2)
        return self.J

    def gradientdescent(self,alpha):
        "Perform gradient descent algorithm"
        self.a=alpha #leaarning rate

        temptheta0=self.t0-self.a*(1./self.m)*sum((self.hy-self.y))
        temptheta1=self.t1-self.a*(1./self.m)*sum(((self.hy-self.y)*self.x))

        self.t0=temptheta0
        self.t1=temptheta1
        return self.t0, self.t1

    def plothyp(self,col,title):
        "Plot current hypothesis"
        plt.figure()
        plt.plot(self.x, self.y, 'ro')
        plt.plot(self.x, self.hy, col)
        #plt.gca().set_xlim(left=0)
        #plt.gca().set_ylim(bottom=0)
        plt.title(title)
        plt.show()

## END CLASS

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

#import data
data = np.loadtxt("data_GD.txt", comments="#", delimiter=",", unpack=False)

gd=BatchGD(data)
## visualize the data

gd.plotdata()
##starting values for hupothesis hy=theta0+theta1*x
gd.t0=1.5
gd.t1=-0.7

#test and plot the starting hypothesis
gd.hy=gd.hypothesis(gd.t0,gd.t1)
gd.plothyp('b','Initial hypothesis')

#calculate initial gradient
gd.J=gd.cost_function()

#define error tolerance:
tol=5

while (gd.J>tol): # of course, you can do this with FOR also :)
                  #for i in range (0,1000):
    gd.hy=gd.hypothesis(gd.t0,gd.t1)
    gd.J=gd.cost_function()
    [gd.t0,gd.t1]=gd.gradientdescent(0.002) ##learning rate==0.002    ## interesting results with 0.2 ;)

    print "Current cost is", gd.J
    print 'Parameters Theta0 and Theta1 are {} and {}, respectively' .format(gd.t0, gd.t1)

print 'Final parameters Theta0 and Theta1 found by GD are {} and {}, respectively' .format(gd.t0, gd.t1)
gd.plothyp('k', 'Final hypothesis')

##END


# -*- coding: utf-8 -*-
"""
Created on Fri Sep  8 17:22:01 2017

@author: Alan
"""

#Black Scholes Model
###############
S = float(input("Please enter the stock price :"))

K = float(input("Please enter the strike price :"))

r = float(input("Please enter the risk-free rate :"))

T = float(input("Please enter the maturing time in year :"))

t = float(input("Please enter the starting time in year :"))

D = float(input("Please enter the annual dividend yield :"))

sigma = float(input("Please enter the annualized volatility :"))

def BS_Call_Value():

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

    d1 = (log(S/K ,exp(1)) + ((r - D + (0.5*(sigma**2)))*(T-t))) / (sigma*sqrt(T-t))
    print("d1 =",d1)
    d2 = d1 - (sigma*sqrt(T-t))
    print("d2 =",d2)

    Nd1 = stats.norm.cdf(d1, 0.0 ,1.0)
    print("N(d1) =",Nd1)

    Nd2 = stats.norm.cdf(d2, 0.0 ,1.0)
    print("N(d2) =",Nd2)

    call_value = float((S*exp(-D*(T-t))*Nd1)- (K*exp(-r*(T-t))*Nd2))
    return call_value

European_Call_Option = BS_Call_Value()
print("European_Call_Option =",European_Call_Option)

def BS_Put_Value():

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

    d1 = (log(S/K ,exp(1)) + ((r - D + (0.5*(sigma**2)))*(T-t))) / (sigma*sqrt(T-t))
    print("d1 =",d1)

    d2 = d1 - (sigma*sqrt(T-t))
    print("d2 =",d2)

    N_d1 = stats.norm.cdf(-d1, 0.0 ,1.0)
    print("N(-d1) =",N_d1)

    N_d2 = stats.norm.cdf(-d2, 0.0 ,1.0)
    print("N(-d2) =",N_d2)

    Put_value = float((K*exp(-r*(T-t))*N_d2)-(S*exp(-D*(T-t))*N_d1))
    return Put_value

European_Put_Option = BS_Put_Value()
print("European_Put_Option =",European_Put_Option)

###################
#Put Call Parity in Black Scholes Model
###################
Put_Call_Parity = round(European_Call_Option - European_Put_Option,2)
print("Put Call Parity =",Put_Call_Parity)

def P_C_Parity():

     from math import exp

     PV_S = S*exp(-D*(T-t))
     print("Present Value of Stock Price =",PV_S)
     PV_K = K*exp(-r*(T-t))
     print("Present Value of Strike Price in Dollar =",PV_K)
     P_C = round(PV_S - PV_K , 2)
     return P_C

Put_Call_Parity = P_C_Parity()
print("Put Call Parity =", Put_Call_Parity)

Black Scholes Model european call and put .py


import math
import numpy as np

__DEBUG__ = False

def compute_entropy(values):
    """
    Given values for a random variable, calculate its entropy.
    :param values: RV
    :return: entropy of random variable with values outcome
    """
    counts = {}
    for val in values:
        try:
            counts[val] += 1
        except KeyError:
            counts[val] = 1
    entropy = 0
    for key, value in counts.items():
        prob = counts[key] / len(values)
        entropy += -1 * prob * math.log(prob, 2)
    return entropy

def compute_expected_info(data, feature, target):
    """
    Compute expected info for a feature given the observation data
    :param data: training data
    :param feature: feature name to process
    :param target: target variable
    :return: expected info
    """
    data_size = data.shape[0]
    expected_info = 0
    for attr_value in data[feature].unique():
        values = data.loc[data[feature] == attr_value][target].values
        expected_info += compute_entropy(values) * len(values) / data_size
    return expected_info

def get_best_feature(data, target):
    """
    Get best feature that gives the purest node!
    :param data: training data
    :param target: target variable
    :return: feature name
    """
    features = list(set(data.columns) - set([target]))
    exp_info_values = []
    for feature in features:
        exp_info = compute_expected_info(data, feature, target)
        exp_info_values.append(exp_info)
        if __DEBUG__:
            print("feature: {} --> info: {}".format(feature, exp_info))
    best_fet_inx = np.argmin(np.array(exp_info_values))
    if __DEBUG__:
        print("feature: {} --> info: {}".format(features[best_fet_inx], min(exp_info_values)))
    return features[best_fet_inx]


# -*- coding: utf-8 -*-
"""
Spyder Editor

This is a temporary script file.
"""
import numpy as np
import matplotlib.pyplot as plt

N = int(input("Pick a number: "))

n, a, sum1, m, b, sum2 = 1, 0, 0, N, 0, 0

while (n<=N):
    a = 1/n
    sum1+=a
    n = n+1

while (m>=1):
    b = 1/m
    sum2+=b
    m = m-1

error = (sum1 - sum2)/(np.absolute(sum1)+np.absolute(sum2))
print("For N = :",N,", the error is: ",error)

N1=1
Ns=[]
Errors=[]

while N1<=N:

    n1, a1, sum11, m1, b1, sum21 = 1, 0, 0, N1, 0, 0

    while (n1<=N1):
        a1 = 1/n1
        sum11+=a1
        n1 = n1+1
    while (m1>=1):
        b1 = 1/m1
        sum21+=b1
        m1 = m1-1

    Ns.append(N1)
    error1 = (sum11 - sum21)/(np.absolute(sum11)+np.absolute(sum21))
    Errors.append(error1)
    N1=N1+1

plt.plot(Ns,Errors,'r-')
plt.xlabel("N")
plt.ylabel("Error(x10^-16)")
plt.title("N vs. Error")
plt.show()

print("The down summation is more precise because the error of the number is proportional to the number you are summing, therefore as the number decreases, there is less error, versus starting with a small number, and adding more error for every summation.")


import numpy as np
# Q. 11. Get the common items between a and b
a = np.array([1,2,3,2,3,4,3,4,5,6])
b = np.array([7,2,10,2,7,4,9,4,9,8])
c = np.intersect1d(a,b)
# print(c)
# 12. How to remove from one array those items that exist in another?
a = np.array([1,2,3,4,5])
b = np.array([5,6,7,8,9])
c = np.setdiff1d(a,b)
# print(c)
# 13. How to get the positions where elements of two arrays match?
a = np.array([1,2,3,2,3,4,3,4,5,6])
b = np.array([7,2,10,2,7,4,9,4,9,8])
# print(np.where(a==b))
# 14. How to extract all numbers between a given range from a numpy array?
# Q. Get all items between 5 and 10 from a
a = np.array([2, 6, 1, 9, 10, 3, 27])
# method 1
print(a[(a >= 5) & (a <= 10)])
# method 2
mask = np.where((a>=5) & (a<=10))
print(a[mask])
# method 3
truthy_mask = np.logical_and(a>=5, a<=10)
index_mask = np.where(truthy_mask)
print(a[index_mask])
# 15. How to make a python function that handles scalars to work on numpy arrays?
# Q. Convert the function maxx that works on two scalars, to work on two arrays.
a = np.array([5, 7, 9, 8, 6, 4, 5])
b = np.array([6, 3, 4, 8, 9, 7, 1])
def pair_max(arr_a, arr_b):
    res = np.empty_like(arr_a)
    for i, (a, b) in enumerate(zip(arr_a, arr_b)):
        if a >= b:
            res[i] = a
        else:
            res[i] = b
    return res
print(pair_max(a, b))
# using the vectorize method
def maxx(x, y):
    """Get the maximum of two items"""
    if x >= y:
        return x
    else:
        return y
pair_max = np.vectorize(maxx, otypes=[int])
print(pair_max(a, b))
# 16. How to swap two columns in a 2d numpy array?
# Q. Swap columns 1 and 2 in the array arr.
arr = np.arange(9).reshape(3,3)
print(arr)
swapped_arr = np.empty_like(arr)
swapped_arr[:,0] = arr[:,0]
swapped_arr[:,1] = arr[:,2]
swapped_arr[:,2] = arr[:,1]
print(swapped_arr)
# better method
swapped_arr = arr[:, [0,2,1]]
print(swapped_arr)
# 17. How to swap two rows in a 2d numpy array?
# Q. Swap rows 1 and 2 in the array arr:
arr = np.arange(9).reshape(3,3)
swapped_arr = arr[[0,2,1],:]
print(swapped_arr)
# 18. How to reverse the rows of a 2D array?
# Q. Reverse the rows of a 2D array arr.
# Input
arr = np.arange(9).reshape(3,3)
print(arr)
reversed_rows_arr = arr[[2,1,0],:]
print(reversed_rows_arr)
# better method, using arr[start:stop:step]
arr = np.arange(9).reshape(3,3)
reversed_rows_arr = arr[::-1]
print(reversed_rows_arr)
# 20. How to create a 2D array containing random floats between 5 and 10?
# Q. Create a 2D array of shape 5x3 to contain random decimal numbers between 5 and 10.

arr = np.random.uniform(low=5, high=11, size=(5,3))
print(arr)
print(arr)

# 21. How to print only 3 decimal places in python numpy array?
# Q. Print or show only 3 decimal places of the numpy array rand_arr.

rand_arr = np.random.random((5,3))

# solution, use: numpy.set_printoptions(precision=None...)
# #from https://het.as.utexas.edu/HET/Software/Numpy/reference/generated/numpy.set_printoptions.html

np.set_printoptions(precision=3)
print(rand_arr)

# 22. How to pretty print a numpy array by suppressing the scientific notation (like 1e10)?
# Q. Pretty print rand_arr by suppressing the scientific notation (like 1e10)

# Create the random array
np.random.seed(100)
rand_arr = np.random.random([3,3])/1e3

# Desired Output (similar to):
#> array([[ 0.000543,  0.000278,  0.000425],
#>        [ 0.000845,  0.000005,  0.000122],
#>        [ 0.000671,  0.000826,  0.000137]])
Define branch protection rules to disable force pushing, prevent branches from being deleted, and optionally require status checks before merging. New to branch protection rules? Learn more.
np.set_printoptions(suppress=True)
print(rand_arr)

# 23. How to limit the number of items printed in output of numpy array?
# Q. Limit the number of items printed in python numpy array a to a maximum of 6 elements.

a = np.arange(15)
#> array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14])
# Desired Output:
#> array([ 0,  1,  2, ..., 12, 13, 14])

np.set_printoptions(threshold=6)
print(a)

# 24. How to print the full numpy array without truncating
# Q. Print the full numpy array a without truncating.

# Input:

a = np.arange(15)
np.set_printoptions(threshold=sys.maxsize)
print(a)
#> array([ 0,  1,  2, ..., 12, 13, 14])

# 25. How to import a dataset with numbers and texts keeping the text intact in python numpy?
# Q. Import the iris dataset keeping the text intact.

import requests
import io

link = "https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data"

response = requests.get(link, verify=False)
response.raise_for_status()
data = np.load(io.BytesIO(response.content))  # Works!

# data = np.loadtxt(link)

print(data)
# Not sure if this one is working because I can't run it on ONS work machine

# LOOKS LIKE np.genfromtxt() would have been a better solution

# 26. How to extract a particular column from 1D array of tuples?
# Q. Extract the text column species from the 1D iris imported in previous question.

url = 'https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data'
iris_1d = np.genfromtxt(url, delimiter=',', dtype=None)

text_col = np.array([row[4] for row in iris_1d])

# 27. How to convert a 1d array of tuples to a 2d numpy array?
# Q. Convert the 1D iris to 2D array iris_2d by omitting the species text field.

# running iris_1d.dtype.names gives us the col names
# The names can be used to access items in the np.void (like a tuple)

# HACKY AS HELL solution using nested list comprehension and unpacking the list of voids
iris_2d = np.array([[*void[['f0', 'f1', 'f2', 'f3']]] for void in iris_1d])

# Given solution using .tolist() method on the np.voids

iris_2d = np.array([row.tolist()[:4] for row in iris_1d])


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

# Load data
x_train = np.load('x_train.npy')
y_train = np.load('y_train.npy')
x_test = np.load('x_test.npy')
y_test = np.load('y_test.npy')

def trace_for_all_data(x_train, y_train, vector_like=True):
    if vector_like:
        for i in range(len(x_train)):
            yield (x_train[i]).reshape(2, 1), y_train[i]
    else:
        for i in range(len(x_train)):
            yield x_train[i], y_train[i]

# 1. Compute the mean vectors mi, (i=1,2) of each 2 classes

def get_mi(x_train, y_train):
    n_1 = 0
    # sum_1 = np.zeros(2)
    # sum_2 = np.zeros(2)
    # for i, e in enumerate(y_train):
    #     print(f'dot: ({x_train[i][0]}, {x_train[i][1]}) -> {y_train[i]}')
    #     if e == 0:
    #         sum_1 += x_train[i]
    #         n_1 += 1
    #     else:
    #         sum_2 += x_train[i]
    #     print(f'update sum: s1= {sum_1}, s2= {sum_2}')
    # return sum_1/ n_1, sum_2/ (len(x_train) - n_1)

    sum_ = np.zeros((2, 2, 1))
    for data in trace_for_all_data(x_train, y_train):
        sum_[data[1]] += data[0]
        n_1 += data[1] == 0
        # print(f'data: {data}')
        # print(f'update sum: s1= {sum_[0]}, s2= {sum_[1]}')
        # print(f'n_1: {n_1}')
    return sum_[0] / n_1, sum_[1] / (len(x_train) - n_1)
    # training data:
    # mean vector of class 1: [ 1.3559426  -1.34746216]
    # mean vector of class 2: [-1.29735587  1.29096203]

m1, m2 = get_mi(x_train, y_train)
print(f"mean vector of class 1:\n{m1}\nmean vector of class 2:\n{m2}\n")
# =================================================================

# 2. Compute the Within-class scatter matrix SW

def get_SW(x_train, y_train, m=None):
    '''
    m: [ m1: 2x1 vector, m2: 2x1 vector ]
    '''
    if m is None:
        m = get_mi(x_train, y_train)

    # Si = sum( (xi - m)(xi - m)T )
    # 2x2 matrix, if xi is 2-D data
    S = np.zeros((2, 2, 2))
    for data in trace_for_all_data(x_train, y_train):
        sub = data[0] - m[data[1]]
        S[data[1]] += sub @ sub.T
        # print(f'   X: {data[0]}')
        # print(f'mean: {m[data[1]]}')
        # print(f' sub: {sub}')
        # print(f'sub @ subT: {sub@sub.T}')
        # print(f'S[{data[1]}]: {S[data[1]]}')
    return S[0] + S[1]

sw = get_SW(x_train, y_train, (m1, m2))
assert sw.shape == (2, 2)
print(f"Within-class scatter matrix SW:\n{sw}\n")
# =================================================================

# 3. Compute the Between-class scatter matrix SB

def get_SB(m1, m2):
    sub = m2 - m1
    return sub @ sub.T

sb = get_SB(m1, m2)
assert sb.shape == (2, 2)
print(f"Between-class scatter matrix SB:\n{sb}\n")
# =================================================================

# 4. Compute the Fisher’s linear discriminant

def get_W(SW, m1, m2):
    w = inv(SW) @ (m2 - m1)
    # |w| = sqrt( wTw )
    # print(f'origin w: {w}')
    w = w / (w.T @ w)**(1/2)
    # print(f' after w: {w}')
    return w

w = get_W(sw, m1, m2)
assert w.shape == (2, 1)
print(f" Fisher’s linear discriminant:\n{w}\n")
# =================================================================

# 5. Project the test data by linear discriminant
#    to get the class prediction by nearest-neighbor rule
#    and calculate the accuracy score

def predict(x_train, y_train, w, x_test):
    '''
    x_test: [
        [x0, x1],
        [x0, x1],
        ...
    ]
    y_test: [
        1, 0, 0, 1, 1, ...
    ]
    w: [
        [w0],
        [w1]
    ]
    return [
        1, 0, 0, 1, 1
    ]
    x_train 投影到 w 上的長度(正負)差異
    x_train @ w = [
        [1.342],
        [-0.023],
        ...
    ]
    '''
    x_train_project = x_train @ w
    x_test_project = x_test @ w

    check_table = np.append(x_train_project,
                            y_train.reshape((-1, 1)),
                            axis=1)
    # check table:
    # [[project val, catgory],
    #  [project val, catgory]]
    # print(check_table)

    # sort by [proj val, ]
    check_table = check_table[np.argsort(check_table[:, 0])]
    # find no. of x_test( by project val to w )
    search_result = np.searchsorted(check_table[:, 0], x_test_project)
    # [1 3 5], 2 -> place in pos "1" -> check distance to "0" and "1"
    # print(f'check:\n{check_table}')
    # print(f'resul:\n{search_result}')

    y_pred = []
    for i, e in enumerate(search_result):
        e = e[0]  # U 夠麻煩...
        # x_test[i] between check table [e-1] to [e]
        # print(f'{x_test_project[i][0]} - {check_table[e-1][0]} vs.')
        # print(f'{check_table[e][0]} - {x_test_project[i][0]}')
        if x_test_project[i][0] - check_table[e-1][0] < \
           check_table[e][0] - x_test_project[i][0]:
            # if distance to e-1 is closer than
            #    distance to e
            y_pred += [check_table[e-1][1]]
        else:
            y_pred += [check_table[e][1]]
    return np.array(y_pred)

y_pred = predict(x_train, y_train, w, x_test)

def accuracy_score(y_test, y_pred):
    '''
    y_test: [1, 0, 0, ...]
    y_pred: [1, 1, 0, ...]

    correct / all
    (y_test == y_pred) / all

    not correct: abs(y_test - y_pred)
    (all-abs(y_test-y_pred)) / all
    '''
    n = len(y_test)
    return (n-sum(abs(y_test-y_pred))) / n

acc = accuracy_score(y_test, y_pred)
print(f"Accuracy of test-set {acc}")
# =================================================================

# 6. Plot the
# 1) best projection line on the training data and show the slope
#    and intercept on the title
#    (you can choose any value of intercept for better visualization)
# 2) colorize the data with each class
# 3) project all data points on your projection line.
# Your result should look like this image

def partition(x_train, y_train):
    '''
    return [
        [x0, x1],
        [x0, x1],
        ...
        [x0, x1]
    ]
    '''
    collect_0 = []
    collect_1 = []
    for x, y in trace_for_all_data(x_train, y_train, vector_like=False):
        if y == 0:
            # plt.plot([x[0]], [x[1]], 'b.')
            collect_0 += [x]
        else:
            # plt.plot([x[0]], [x[1]], 'r.')
            collect_1 += [x]
    collect_0 = np.array(collect_0)
    collect_1 = np.array(collect_1)
    return collect_0, collect_1

def Plot_point(x_train, y_train):
    collect_0, collect_1 = partition(x_train, y_train)
    # plt.plot(collect_0[0][0], collect_0[0][1], 'b.')
    plt.plot(collect_0.T[0], collect_0.T[1], 'bo')
    plt.plot(collect_1.T[0], collect_1.T[1], 'ro')

def Plot_line(w, b, from_x, to_x):
    # y_dist / x_dist
    a = w[1][0] / w[0][0]
    # y = a x + b
    plt.title(f'ProjectionLine: w={a}, b={b}')
    plt.plot(
        [from_x, to_x],
        [a * from_x + b, a * to_x + b],
        'k-'
    )

def Plot_point_on_line(x_train, y_train, w, b, from_x, to_x):
    collect_0, collect_1 = partition(x_train, y_train)
    # x0, x1 = collect_0[0]
    # project = (x0*w[0][0] + (x1-b)*w[1][0]) * w
    # point = [project[0][0], project[1][0] + b]
    # plt.plot(*point, 'b.')

    # plt.plot([x0, point[0]], [x1, point[1]], 'b--')
    # # a = (x1-x0)*w[0] + (point[1] - point[0])*w[1]
    # print()

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

    c_0 = []
    c_1 = []
    pairs = []
    for x0, x1 in collect_0:
        # project = np.array([[x0], [x1-b]]).dot(w) * w
        project = (x0*w[0][0] + (x1-b)*w[1][0]) * w
        point = [project[0][0], project[1][0] + b]
        c_0 += [point]
        pairs += [[[x0, x1], point]]
    for x0, x1 in collect_1:
        # project = np.array([[x0], [x1-b]]).dot(w) * w
        project = (x0*w[0][0] + (x1-b)*w[1][0]) * w
        point = [project[0][0], project[1][0] + b]
        c_1 += [point]
        pairs += [[[x0, x1], point]]

    c_0 = np.array(c_0)
    c_1 = np.array(c_1)
    pairs = np.array(pairs)

    plt.plot(c_0.T[0], c_0.T[1], 'bo')
    plt.plot(c_1.T[0], c_1.T[1], 'ro')
    for p1, p2 in pairs:
        plt.plot([p1[0], p2[0]], [p1[1], p2[1]], 'c:')

def Plot_all(x_train, y_train, w, b, from_x, to_x):
    # set x, y size
    plt.figure(figsize=(8, 8), dpi=80)
    plt.xlim(-6, 4)
    plt.ylim(-5, 5)

    Plot_point(x_test, y_test)
    Plot_line(**line_information)
    Plot_point_on_line(x_test, y_test, **line_information)
    plt.show()

line_information = {
    'w': w,
    'b': -3.5,
    'from_x': -6,
    'to_x': 4
}

Plot_all(x_train, y_train, **line_information)


# -*- coding: utf-8 -*-
"""
Created on Wed Sep 23 11:20:19 2020

@author: Ruben Andre Barreiro
"""

# Import NumPy Python's Library
import numpy as np

# Import Matplotlib Python's Library
import matplotlib.pyplot as plt

# Load the Matrix with the Polynomial Data
mat = np.loadtxt('../files/polydata.csv',delimiter=';')

# Set the X values, from the Polynomial Data
x = mat[:,0]

# Set the Y values, from the Polynomial Data
y = mat[:,1]

# Set the Coefficients, of Degree 3
coefs_3 = np.polyfit(x,y,3)

# Set the Coefficients, of Degree 15
coefs_15 = np.polyfit(x,y,15)

# Set the Pixels, for the Linear Space
pxs = np.linspace(0,max(x),100)

# Fit a 3rd Degree Polynomial function
poly_3 = np.polyval(coefs_3,pxs)

# Fit a 15th Degree Polynomial function
poly_15 = np.polyval(coefs_15,pxs)

# Create a Figure for Plotting
plt.figure(figsize=(12, 8))

# Plot the points of the Polynomial data
plt.plot(x,y,'or')

# Plot the Fitted 3rd Degree Polynomial Function
plt.plot(pxs,poly_3,'-')

# Plot the Fitted 15th Degree Polynomial Function
plt.plot(pxs,poly_15,'-')

# Set the Axis for the Plotting Chart
plt.axis([0,max(x),-1.5,1.5])

# Set the Title for the Plotting Chart
#plt.title('Degree: 3')
#plt.title('Degree: 15')
plt.title('Degree: 3 and 15')

# Save a figure for the Plotting of the Polynomial data points
# NOTE: This needs to be done always after the plot function
#       and before the close function
#plt.savefig('../files/imgs/1.6-exercise-2-coef-3.png')
#plt.savefig('../files/imgs/1.6-exercise-2-coef-15.png')
plt.savefig('../files/imgs/1.6-exercise-2-coefs-3-and-15.png')

# Close the Figure for Plotting
plt.close()

# Print the Coefficients of the 3rd Degree Polynomial Function
print('\n')
print('The Coefficients of the 3rd Degree Polynomial Function:')
print(coefs_3)

# Print the Coefficients of the 15th Degree Polynomial Function
print('\n')
print('The Coefficients of the 15th Degree Polynomial Function:')
print(coefs_15)

# Exercise 1.6.1:
# Q: What is the hypothesis class you are using in each case
#    (degree 3 and degree 15)?
# A: Degree 3: A polynomial curve of degree 3
#    Degree 15: A polynomial curve of degree 15

# Exercise 1.6.2:
# Q: What is the corresponding model for each hypothesis class?
# A: Degree 3: y = θ_{1}x^{3} + θ_{2}x^{2} + θ_{3}x + θ_{4}
#    Degree 15: y = θ_{1}x^{15} + θ_{2}x^{14} + θ_{3}x^{13} + θ_{4}x^{12} +
#                 + θ_{5}x^{11} + θ_{6}x^{10} + θ_{7}x^{9} + θ_{8}x^{8} +
#                 + θ_{9}x^{7} + θ_{10}x^{6} + θ_{11}x^{5} + θ_{12}x^{4} +
#                 + θ_{13}x^{3} + θ_{14}x^{2} + θ_{15}x + θ_{16}

# Exercise 1.6.3:
# Q: What is the hypothesis in each case?
# A: Degree 3:  [ θ_{1} = 0.12831139 ; θ_{2} = -1.24583487 ;
#                 θ_{3} = 3.01638739 ; θ_{4} = -1.10432872 ]
#    Degree 15: [ θ_{1} = -1.16565156e-03 ; θ_{2} = 5.94797587e-02 ;
#                 θ_{3} = -1.39485584e+00 ; θ_{4} = 1.99433035e+01 ;
#                 θ_{5} = -1.94455094e+02 ; θ_{6} = 1.36991372e+03 ;
#                 θ_{7} = -7.20494944e+03 ; θ_{8} = 2.88096907e+04 ;
#                 θ_{9} = -8.82893589e+04 ; θ_{10} = 2.07259302e+05 ;
#                 θ_{11} = -3.69289141e+05 ; θ_{12} = 4.89713241e+05 ;
#                 θ_{13} = -4.66923307e+05 ; θ_{14} = 3.01463118e+05 ;
#                 θ_{15} = -1.17541384e+05 ; θ_{16} = 2.08092837e+04 ]

# Exercise 1.6.4:
# Q: How was each hypothesis chosen?
# A: Instantiating the parameters' vector (theta), representing the vector of
#    all theta_{1}; ... ; theta_{n} parameters.
#    The probability of the data given the hypothesis is
#    the likelihood of the hypothesis.
#    The best hypothesis is the one with the best (or maximum) likelihood
#    However, in some cases, increasing too much the degree of
#    a Polynomial Curve, can lead to not a good prediction of future values,
#    because the range of Polynomial Curve is very stricted to the data used
#    So, a good idea is to separate the global set in two subsets:
#    1) Training Set: The subset for training the Model;
#    2) Test Set: The subset for test the Model and predict the future values;


## 3. Bikesharing distribution ##

import pandas
bikes = pandas.read_csv("bike_rental_day.csv")
prob_over_5000 = bikes[bikes["cnt"] > 5000].shape[0] / bikes.shape[0]

## 4. Computing the distribution ##

import math

# Each item in this list represents one k, starting from 0 and going up to and including 30.
outcome_counts = list(range(31))
def find_probability(N, k, p, q):
    # Find the probability of any single combination.
    term_1 = p ** k
    term_2 = q ** (N-k)
    combo_prob = term_1 * term_2

    # Find the number of combinations.
    numerator = math.factorial(N)
    denominator = math.factorial(k) * math.factorial(N - k)
    combo_count = numerator / denominator

    return combo_prob * combo_count

outcome_probs = [find_probability(30, i, .39, .61) for i in outcome_counts]

## 5. Plotting the distribution ##

import matplotlib.pyplot as plt

# The most likely number of days is between 10 and 15.
plt.bar(outcome_counts, outcome_probs)
plt.show()

## 6. Simplifying the computation ##

import scipy
from scipy import linspace
from scipy.stats import binom

# Create a range of numbers from 0 to 30, with 31 elements (each number has one entry).
outcome_counts = linspace(0,30,31)
dist = binom.pmf(outcome_counts,30,0.39)
plt.bar(outcome_counts, dist)
plt.show()

## 8. Computing the mean of a probability distribution ##

dist_mean = None
dist_mean = 30 * .39

## 9. Computing the standard deviation ##

dist_stdev = None
dist_stdev = (30*0.39*0.61)** (1/2)

## 10. A different plot ##

# Enter your answer here.
import scipy
from scipy import linspace
from scipy.stats import binom
outcome_counts = linspace(0,10,11)
dist = binom.pmf(outcome_counts,10,0.39)
plt.bar(outcome_counts,dist)
plt.show()
outcome_counts = linspace(0,100,101)
dist = binom.pmf(outcome_counts,100,0.39)
plt.bar(outcome_counts,dist)
plt.show()

## 11. The normal distribution ##

# Create a range of numbers from 0 to 100, with 101 elements (each number has one entry).
outcome_counts = scipy.linspace(0,100,101)

# Create a probability mass function along the outcome_counts.
outcome_probs = binom.pmf(outcome_counts,100,0.39)

# Plot a line, not a bar chart.
plt.plot(outcome_counts, outcome_probs)
plt.show()

## 12. Cumulative density function ##

outcome_counts = linspace(0,30,31)
outcome_probs = binom.cdf(outcome_counts,30,0.39)
plt.plot(outcome_counts, outcome_probs)
plt.show()

## 14. Faster way to calculate likelihood ##

left_16 = None
right_16 = None

left_16 = binom.cdf(16,30,0.39)
right_16 = 1 - left_16

Probability Statistics Intermediate/Probability distributions-135.py


import numpy as np

class linearSys:
    def __init__(self, A, b):
        self.A = A
        self.b = b
        self.n = A.shape[0]
        self.L = np.eye(self.n)
        self.U = np.eye(self.n)
        self.x = np.zeros([self.n, 1])
        self.y = np.zeros([self.n, 1])

    def LU_Decompose(self):
        if self.A[0, 0] != 0:
            self.L[0, 0] = self.A[0, 0]
            self.U[0, 1:] = self.A[0, 1:] / self.L[0, 0]
            self.L[1:, 0] = self.A[1:, 0] / self.U[0, 0]
            for i in range(1, self.n - 1):
                self.L[i, i] = self.A[i, i] - np.dot(self.L[i, 0:i], self.U[0:i, i])
                if self.L[i, i] != 0:
                    self.U[i, i+1:] = (self.A[i, i+1:] - np.dot(self.L[i, 0:i], self.U[0:i, i+1:])) / self.L[i, i]
                    self.L[i+1:, i] = (self.A[i+1:, i] - np.dot(self.L[i+1:, 0:i], self.U[0:i, i])) / self.U[i, i]
                else:
                    return 'Factorization impossible at l{0}{0}'.format(i+1)

            self.L[-1, -1] = self.A[-1, -1] - np.dot(self.L[-1, 0:-1], self.U[0:-1, -1])
            if self.L[-1, -1] == 0:
                print('A is singular')

            self.y[0] = self.b[0] / self.L[0, 0]
            for i in range(1, self.n):
                self.y[i, 0] = (self.b[i] - np.dot(self.L[i, 0:i], self.y[0:i, 0])) / self.L[i, i]

            self.x[-1] = self.y[-1] / self.U[-1, -1]
            for i in range(self.n - 2, -1, -1):
                self.x[i, 0] = (self.y[i, 0] - np.dot(self.U[i, i+1:], self.x[i+1:, 0])) / self.U[i, i]

            return self.x, self.L, self.U
        else:
            return 'Factorization impossible at a11'

    def LLt_Decompose(self):
        self.L[0, 0] = np.sqrt(self.A[0, 0])
        self.L[1:, 0] = self.A[1:, 0] / self.L[0, 0]
        for i in range(1, self.n - 1):
            self.L[i, i] = np.sqrt(self.A[i, i] - np.sum(self.L[i, 0:i] ** 2))
            self.L[i+1:, i] = (self.A[i+1:, i] - np.sum(self.L[i+1:, 0:i] * self.L[i, 0:i], axis=1)) / self.L[i, i]
        self.L[-1, -1] = np.sqrt(self.A[-1, -1] - np.sum(self.L[-1, 0:-1] ** 2))
        self.y[0] = self.b[0] / self.L[0, 0]
        for i in range(1, self.n):
            self.y[i, 0] = (self.b[i] - np.dot(self.L[i, 0:i], self.y[0:i, 0])) / self.L[i, i]

        self.x[-1] = self.y[-1] / self.L[-1, -1]
        for i in range(self.n - 2, -1, -1):
            self.x[i, 0] = (self.y[i, 0] - np.dot(self.L[i+1:, i], self.x[i+1:, 0])) / self.L[i, i]

        return self.x

def array2latex(arr):
    s = ''
    for k in range(len(arr)):
        row = arr[k]
        if k < len(arr) - 1:
            s += ' & '.join(map(str, row)) + ' \\\\\n'
        else:
            s += ' & '.join(map(str, row))
    return s

if __name__ == '__main__':
    # A = np.array([[1,1,0,3], [2,1,-1,1], [3,-1,-1,2], [-1,2,3,-1]])
    # b = np.array([1, 1, -3, 4])
    A = np.array([[1,1,0,3], [2,1,-1,1], [3,-1,-1,2], [-1,2,3,-1]])
    b = np.array([8, 7, 14, -7])
    sol = linearSys(A, b)
    try:
        # x, L, U = sol.LU_Decompose()
        x, L, U = sol.LLt_Decompose()
        print('Solution:', x.T)
        print('L=\n', array2latex(L))
        print('U=\n', array2latex(U))
    except ValueError:
        print(sol.LU_Decompose())


from typing import Optional

import numpy as np

from mygrad import Tensor
from mygrad.operation_base import Operation
from mygrad.typing import ArrayLike, Real

__all__ = ["selu"]

_ALPHA = 1.6732632423543772848170429916717
_SCALE = 1.0507009873554804934193349852946

class SELU(Operation):
    """Returns the scaled exponential linear activation (SELU) elementwise along x. The SELU is
    given by  λɑ(exp(x) - 1) for x < 0 and λx for x ≥ 0.

    Notes
    -----
    The SELU activation was proposed in the paper
        Self-Normalizing Neural Networks
        Günter Klambauer, Thomas Unterthiner, Andreas Mayr, Sepp Hochreiter
    at https://arxiv.org/abs/1706.02515
    """

    def __call__(self, x):
        """
        Parameters
        ----------
        x : mygrad.Tensor
            Input data.

        Returns
        -------
        numpy.ndarray
            The SELU function applied to `x` elementwise.
        """
        self.variables = (x,)

        x = x.data
        self.exp = _ALPHA * (np.exp(x) - 1)
        return _SCALE * np.where(x < 0, self.exp, x)

    def backward_var(self, grad, index, **kwargs):
        x = self.variables[index]
        return grad * _SCALE * np.where(x.data < 0, self.exp + _ALPHA, 1)

def selu(x: ArrayLike, *, constant: Optional[bool] = None) -> Tensor:
    """Returns the scaled exponential linear activation (SELU) elementwise along x.

    The SELU is given by  λɑ(exp(x) - 1) for x < 0 and λx for x ≥ 0.

    Parameters
    ----------
    x : ArrayLike
        Input data.

    constant : Optional[bool]
        If ``True``, the returned tensor is a constant (it
        does not back-propagate a gradient)

    Returns
    -------
    mygrad.Tensor
        The SELU function applied to `x` elementwise.

    References
    ----------
    .. [1] Günter Klambauer, Thomas Unterthiner, Andreas Mayr, Sepp Hochreiter
       Self-Normalizing Neural Networks
       https://arxiv.org/abs/1706.02515

    Examples
    --------
    >>> import mygrad as mg
    >>> from mygrad.nnet.activations import selu
    >>> x = mg.arange(-5, 6)
    >>> x
    Tensor([-5, -4, -3, -2, -1,  0,  1,  2,  3,  4,  5])
    >>> y = selu(x, alpha=0.1); y
    Tensor([-1.74625336, -1.72589863, -1.67056873, -1.52016647, -1.11133074,
         0.        ,  1.05070099,  2.10140197,  3.15210296,  4.20280395,
         5.25350494])

    .. plot::

       >>> import mygrad as mg
       >>> from mygrad.nnet.activations import selu
       >>> import matplotlib.pyplot as plt
       >>> x = mg.linspace(-2, 2, 100)
       >>> y = selu(x)
       >>> plt.title("selu(x)")
       >>> y.backward()
       >>> plt.plot(x, x.grad, label="df/dx")
       >>> plt.plot(x, y, label="f(x)")
       >>> plt.legend()
       >>> plt.grid()
       >>> plt.show()
    """
    return Tensor._op(SELU, x, constant=constant)


import numpy as np
import ast
import json
def jacobi(A, b, x, norm, tol, iteMax):
    A = ast.literal_eval(A)
    b = ast.literal_eval(b)
    x = ast.literal_eval(x)
    result = {}
    iters = []
    D = np.diag(np.diag(A))
    L = (-1 * np.tril(A))+D
    U = (-1 * np.triu(A))+D
    if(0 in np.diag(A)): return {"status" : "diagonal has 0", "error" : True}
    ite = 0
    #Change here for Jacobi, Sor and Gauss seidel
    T = np.dot(np.linalg.inv(D), (L+U))
    C = np.dot(np.linalg.inv(D),b)
    #End changes
    spectRad = np.max(np.absolute(np.linalg.eigvals(T)))
    if(spectRad > 1): return {"status" : "spectral radious > 1", "error" : True}
    #Saving into result dict
    result['tmatrix'] = json.dumps(T.tolist())
    result['cmatrix'] = json.dumps(C.tolist())
    result['spectrad'] = spectRad

    iters.append({ "iter" : ite, "E" : "n/a", "x" : x})
    #End savings
    while(norm > tol and ite < iteMax):
        xold = x
        x = np.dot(T,xold)+C
        norm = np.linalg.norm(xold-x)
        ite += 1
        #Saving into iters
        iters.append({ "iter" : ite,  "E" : float(norm),  "x" : x.tolist()})
        #End saving
    result['iters'] = iters
    result['error'] = False
    return result


import numpy as np
import settings as globalv

def centerData(data):
	print('\nCentering data...')
	mean_vector = np.mean(data, axis = 1).reshape(data.shape[0], 1)
	centered_data = data - mean_vector

	if (globalv.print_results):
		print('Mean vector: \n', mean_vector)
		print('Centered data: \n', centered_data)
	return centered_data, mean_vector

def correlationMatrix(centered_data):
	print('\nComputing correlation matrix...')
	D = globalv.D
	N = globalv.N

	correlation_matrix = np.zeros((D, D))
	for i in range(N):
		correlation_matrix += (centered_data[:,i].reshape(D,1)).dot(centered_data[:,i].reshape(D,1).T)
	correlation_matrix = correlation_matrix/N

	if (globalv.print_results):
		print(correlation_matrix)

	return correlation_matrix

def eigenDecomposition(corr):
	print('\nEigendecomposition of correlation matrix...')
	D = globalv.D
	N = globalv.N

	eigvals, eigvecs = np.linalg.eig(corr)

	for i in range(len(eigvals)):
		eigv = eigvecs[:,i].reshape(1,D).T
		np.testing.assert_array_almost_equal(corr.dot(eigv), eigvals[i] * eigv, decimal=6, err_msg='', verbose=True)

	if (globalv.print_results):
		print('Eigenvalues: \n', eigvals)
		print('Eigenvectors: \n', eigvecs)

	return eigvals, eigvecs

def readUserNumComponents(msg):
	D = globalv.D
	N = globalv.N

	# numComponents = raw_input(msg)
	numComponents = 4
	# try:
		# Try to convert the user input to an integer
	    # numComponents = int(numComponents)
		# if numComponents > D or numComponents < 0:
		# 	print 'Invalid number of components'
		# 	sys.exit(-3)
	# except ValueError:
	# 	Catch the exception if the input was not a number
		# numComponents = 1
	# print 'Using %d components' %numComponents
	return numComponents

def computeProjectionMatrix(eigvals, eigvecs, r):
	print('\nComputing the projection matrix...')
	D = globalv.D
	N = globalv.N

	# List of (eigenvalue, eigenvector) tuples
	eig_pairs = [(np.abs(eigvals[i]), eigvecs[:,i]) for i in range(len(eigvals))]

	# Sort the (eigenvalue, eigenvector) tuples from high to low (reverse=True)
	eig_pairs.sort(key=lambda tup: tup[0], reverse=True)

	# Projection matrix
	proj_matrix = np.zeros((D,r))
	for i in range(r):
		proj_matrix[:,i] = eig_pairs[i][1].reshape(1, D)

	if (globalv.print_results):
		print('Projection matrix: \n', proj_matrix)

	return proj_matrix

def computePrincipalComponents(centered_data, proj_matrix):
	print('\nComputing principal components...')
	p = (proj_matrix.T).dot(centered_data)

	if (globalv.print_results):
		print('Principal components: \n', p)

	return p

def reconstructData(princ_comps, proj_matrix, mean_vector):
	print('\nReconstructing the data...')
	reconstructed_data = (proj_matrix).dot(princ_comps) + mean_vector

	if (globalv.print_results):
		print('Reconstructed data: \n', reconstructed_data)

	return reconstructed_data

def computeRecError(data, reconstructed_data):
	print('\nComputing reconstruction error...')
	D = globalv.D
	N = globalv.N

	error = data - reconstructed_data
	error_var = 0
	for i in range(N):
		error_var += np.linalg.norm(error[:, i])**2
	error_var = error_var/N

	if (globalv.print_results):
		print('Error: \n', error)
	print('Error variance: ', error_var)

	return error


import numpy as np
import matplotlib.pyplot as plt

def least_square_algorithm(t, y, n):
    """ Least square algorithm

    Args:
        t: list/ndarray, the list of points
        y: list/ndarray, the list of function value
        n: int, the order of the fitting curve

    Returns:
        c: ndarray, the cofficients of the fitting curve
    """
    # the number of the points
    leng = len(t)
    # the cofficient matrix
    A = np.ones(leng)
    for i in range(n):
        A = np.c_[A, t**(i+1)]
    # the solution of the normal equations
    c = np.linalg.solve(A.T.dot(A), A.T.dot(y))

    return c

def calculate_square_error(y, func):
    """ Calculate the square error

    Args:
        y: ndarray, the list of prediction value
        func: ndarray, the list of original value

    Returns:
        sq_err: double, the square error
    """
    return np.sum(np.square(y - func))

def draw_curve(x, y, func, file_name):
    """ Draw the fitting curve

    Args:
        x: ndarray, the data of independent variable
        y: ndarray, the original value
        func: ndarray, the prediction function
        file_name: string, the name of the saved figure file

    """
    fig = plt.figure(figsize=(6, 6))
    plt.plot(x, y, 'ro', label='data set')
    t = np.arange(x[0], x[-1], 0.1)
    plt.plot(t, func(t), 'g-', label='fitting curve')
    plt.title('Least Square Algorithm')
    plt.legend()
    plt.savefig(file_name)

def linear_fitting():
    """ Fitting experiment 1

    """
    # data
    x = np.array([1, 2, 3, 4, 5])
    y = np.array([4, 4.5, 6, 8, 8.5])
    # get the cofficients
    a, b = least_square_algorithm(x, y, 1)
    # define the fitting curve using the cofficients
    f = lambda x: a + b * x
    # get the square error
    print(f"The linear fitting's square error is {calculate_square_error(f(x), y)}")
    # visualization
    draw_curve(x, y, f, 'linear_fitting.png')

def non_linear_fitting():
    """ two order polinomial fitting

    """
    # data
    x = np.array([2, 3, 4, 7, 8, 10, 11, 14, 16, 18, 19])
    y = np.array([106.42, 108.2, 109.5, 110, 109.93, 110.49, 110.59, 110.6, 110.76, 111, 111.2])
    # get the cofficients
    a, b, c = least_square_algorithm(x, y, 2)
    # define the fitting curve
    f = lambda x: a + b * x + c * x**2
    # get the square error
    print(f"The 2-order polinomial fitting's square error is {calculate_square_error(f(x), y)}")
    # visualization
    draw_curve(x, y, f, 'polinomial_fitting.png')

    """ exponential fitting

    """
    # data preprocessing
    t = 1 / x
    z = np.log(y)
    # get the cofficients
    a0, b0 = least_square_algorithm(t, z, 1)
    a1, b1 = np.exp(a0), b0
    # define the fitting curve
    g = lambda x: a1 * np.exp(b1 / x)
    print(f"The exponential fitting's square error is {calculate_square_error(g(x), y)}")
    # visualization
    draw_curve(x, y, g, 'exponential_fitting.png')

if __name__ == '__main__':
    linear_fitting()
    non_linear_fitting()


#!/usr/bin/env python
"""Module providing functionality surrounding gaussian function.
"""
SVN_REVISION = '$LastChangedRevision: 16541 $'

import sys
import numpy

def gaussian2(size, sigma):
    """Returns a normalized circularly symmetric 2D gauss kernel array

    f(x,y) = A.e^{-(x^2/2*sigma^2 + y^2/2*sigma^2)} where

    A = 1/(2*pi*sigma^2)

    as define by Wolfram Mathworld
    http://mathworld.wolfram.com/GaussianFunction.html
    """
    A = 1/(2.0*numpy.pi*sigma**2)
    x, y = numpy.mgrid[-size//2 + 1:size//2 + 1, -size//2 + 1:size//2 + 1]
    g = A*numpy.exp(-((x**2/(2.0*sigma**2))+(y**2/(2.0*sigma**2))))
    return g

def fspecial_gauss(size, sigma):
    """Function to mimic the 'fspecial' gaussian MATLAB function
    """
    x, y = numpy.mgrid[-size//2 + 1:size//2 + 1, -size//2 + 1:size//2 + 1]
    g = numpy.exp(-((x**2 + y**2)/(2.0*sigma**2)))
    return g/g.sum()

def main():
    """Show simple use cases for functionality provided by this module."""
    from mpl_toolkits.mplot3d.axes3d import Axes3D
    import pylab
    argv = sys.argv
    if len(argv) != 3:
        print >>sys.stderr, 'usage: python -m pim.sp.gauss size sigma'
        sys.exit(2)
    size = int(argv[1])
    sigma = float(argv[2])
    x, y = numpy.mgrid[-size//2 + 1:size//2 + 1, -size//2 + 1:size//2 + 1]

    fig = pylab.figure()
    fig.suptitle('Some 2-D Gauss Functions')
    ax = fig.add_subplot(2, 1, 1, projection='3d')
    ax.plot_surface(x, y, fspecial_gauss(size, sigma), rstride=1, cstride=1,
                    linewidth=0, antialiased=False, cmap=pylab.jet())
    ax = fig.add_subplot(2, 1, 2, projection='3d')
    ax.plot_surface(x, y, gaussian2(size, sigma), rstride=1, cstride=1,
                    linewidth=0, antialiased=False, cmap=pylab.jet())
    pylab.show()
    return 0

if __name__ == '__main__':
    sys.exit(main())


# Project Euler Problem 5 Solution
#
# Problem statement:
# 2520 is the smallest number that can be divided by each of
# the numbers from 1 to 10 without any remainder.
# What is the smallest positive number that is evenly divisible
# by all of the numbers from 1 to 20?
#
# Solution description:
# This script is a brute-force solution of the above problem,
# followed by a faster solution exploiting prime number factorization.
#
# Author: Daniel Schuette, Philipp Schuette
# Date: 2019/02/09
# License: MIT (see ../LICENSE.md)
import time

import numpy as np

def evenly_divisible(limit):
    """
    Doc string
    """
    current_num = limit  # represents the currently tested number
    divisible = True  # whether `current_num' is still divisible

    while True:
        for divisor in range(1, limit+1):
            if not (current_num % divisor) == 0:
                divisible = False
                break  # break out of for loop

        if not divisible:
            current_num += limit
            divisible = True
        else:
            return current_num

def check_prime(x):
    """
    checks, whether or not x is a prime number
    """
    prime = True
    for i in range(2, x):
        if (x % i) == 0:
            prime = False
            break
    return prime

def prime_list(n):
    """
    outputs a list of all prime numbers between 1 and n > 1
    """
    prime_list = []
    for i in range(2, n + 1):
        if check_prime(i):
            prime_list.append(i)
    return prime_list

def lcm(n):
    """
    outputs the least common multiple for the numbers from 1 to 20
    """
    primes = prime_list(n)
    lcm = 1
    for p in primes:
        e_p = 1
        while pow(p, e_p + 1) <= n:
            e_p += 1
        lcm *= pow(p, e_p)
    return lcm

if __name__ == "__main__":
    # calculate the solution with the 'slow' variant
    start1 = time.time()
    solution1 = evenly_divisible(20)
    end1 = time.time()
    # calculate the solution with the 'fast' variant
    start2 = time.time()
    solution2 = lcm(30)
    end2 = time.time()

    # print both solutions
    print("slow solution expired: {}s, solution: {}".format(
        np.round(end1 - start1, 5), solution1))
    print("fast solution expired: {}s, solution {}". format(
        np.round(end2 - start2, 5), solution2))


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Mon Oct  7 10:11:19 2019

@author: amandaash
"""

import numpy as np
import scipy.optimize as opt
import matplotlib.pyplot as plt

E_b = np.arange(0,10,0.001)
f_Eb = (((10-E_b)**(0.5))*np.tan((10-E_b)**(0.5))) - E_b**(0.5)

plt.plot(E_b, f_Eb)
plt.ylim(-10,10)
plt.grid()
plt.axvline(x = 8.592785275230653, color = 'k', linestyle = 'dashed')
#plt.yscale('log')
plt.savefig('binding_func_10_even.pdf')
plt.show()

def binding_energy(Eb):
    f = (((10-Eb)**(0.5))*np.tan((10-Eb)**(0.5))) - Eb**(0.5)
    return f

E_b_bisect = opt.bisect(binding_energy,8,9.5)

E_b_newton = opt.newton(binding_energy, 8.5)

E_b_brents = opt.brentq(binding_energy, 8.5, 9.5)

print('root even function: bisection method = {0}, precision = {1}'.format(E_b_bisect, binding_energy(E_b_bisect)))
print('root even function: Newton method = {0}, precision = {1}'.format(E_b_newton, binding_energy(E_b_newton)))
print('root even function: brents method = {0}, precision = {1}'.format(E_b_brents, binding_energy(E_b_brents)))
def binding_energy_beta(Eb):
    f = (np.sqrt(Eb)*(np.tan(np.sqrt(10-Eb))**-1))-np.sqrt(10-Eb)
    return(f)

energies = np.arange(0,10,0.001)
fE = binding_energy_beta(energies)

plt.plot(energies, fE)
plt.ylim(-20,10)
plt.axvline(x = 8.592785275230653, color = 'k', linestyle = 'dashed')
plt.grid()
plt.savefig('binding_func_10_odd.pdf')
plt.show()

Eb_bisect_beta = opt.bisect(binding_energy_beta,8,9.5)
print("root odd function: bisection method = {0}".format(Eb_bisect_beta))
E_b_newton_beta = opt.newton(binding_energy_beta, 8.5)
print("root odd function: Newton method = {0}".format(E_b_newton_beta))

def binding_energy_gamma(E, A):
    f = (((A-E)**(0.5))*np.tan((A-E)**(0.5))) - E**(0.5)
    return f

energy_gamma1 = np.arange(0,10,0.001)
energy_gamma2 = np.arange(0,20,0.001)
energy_gamma3 = np.arange(0,30,0.001)

plt.plot(energy_gamma1, binding_energy_gamma(energy_gamma1, 10))
plt.ylim(-10,10)
plt.grid()
plt.show()
plt.title('Binding energy = 20')
plt.plot(energy_gamma2, binding_energy_gamma(energy_gamma2, 20))
plt.ylim(-20,20)
plt.grid()
plt.savefig('binding_func_20_even.pdf')
plt.show()
def binding_energy_gamma20(E):
    f = (((20-E)**(0.5))*np.tan((20-E)**(0.5))) - E**(0.5)
    return f
Eb_bisect_gamma20_root1 = opt.bisect(binding_energy_gamma20,5,7.5)
Eb_bisect_gamma20_root2 = opt.bisect(binding_energy_gamma20,17.7,19)

print(Eb_bisect_gamma20_root1, binding_energy_gamma20(Eb_bisect_gamma20_root1))
print(Eb_bisect_gamma20_root2, binding_energy_gamma20(Eb_bisect_gamma20_root2))
plt.title('Binding energy = 30')
plt.plot(energy_gamma3, binding_energy_gamma(energy_gamma3, 30))
plt.ylim(-30,30)
plt.grid()
plt.savefig('binding_func_30_even.pdf')
plt.show()
def binding_energy_gamma30(E):
    f = (((30-E)**(0.5))*np.tan((30-E)**(0.5))) - E**(0.5)
    return f
Eb_bisect_gamma30_root1 = opt.bisect(binding_energy_gamma30,14,16)
Eb_bisect_gamma30_root2 = opt.bisect(binding_energy_gamma30,28,29.5)

print(Eb_bisect_gamma30_root1, binding_energy_gamma30(Eb_bisect_gamma30_root1))
print(Eb_bisect_gamma30_root2, binding_energy_gamma30(Eb_bisect_gamma30_root2))


from helper import load_times, str_time_to_num_time

import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression

# Load in 5k times and VDOT scores
df = load_times()
df = df[['VDOT', '5k']]
df['5k Time'] = df['5k'].apply(lambda x: str_time_to_num_time(x))

# Create a plot of 5k times against VDOT
df.plot(y='VDOT',
        x='5k Time',
        kind='scatter',
        grid=True,
        title='5k Times Against VDOT')
plt.xticks(ticks=[900, 1200, 1500, 1800],
           labels=['15:00', '20:00', '25:00', '30:00'])
plt.savefig('../generated-notes/5k-models/regular-plot.png')

####################
# We will create a linear regression model and plot results

# Plot a linear regression
model = LinearRegression().fit(df[['5k Time']], df['VDOT'])
print(model.coef_)
print(model.intercept_)
print(model.score(df[['5k Time']], df['VDOT']))

# Get presumed VDOTs from model
plot_space = np.linspace(700, 1900, num=50)
vdots = model.intercept_ + (plot_space * model.coef_[0])

# Plot true, and model predictions
df.plot(y='VDOT',
        x='5k Time',
        kind='scatter',
        grid=True,
        title='5k Times Against VDOT (with Linear Regression Model)')
plt.xticks(ticks=[900, 1200, 1500, 1800],
           labels=['15:00', '20:00', '25:00', '30:00'])
plt.plot(plot_space, vdots)
plt.savefig('../generated-notes/5k-models/linear-plot.png')

####################
# We will create multiple regression models and plot results

# Create multiple regression models
df['5k_1'] = df['5k Time']
df['5k_2'] = df['5k_1'] * df['5k_1']
df['5k_3'] = df['5k_2'] * df['5k_1']
df['5k_4'] = df['5k_3'] * df['5k_1']
model_1 = LinearRegression().fit(df[['5k_1']], df['VDOT'])
model_2 = LinearRegression().fit(df[['5k_1', '5k_2']], df['VDOT'])
model_3 = LinearRegression().fit(df[['5k_1', '5k_2', '5k_3']], df['VDOT'])
model_4 = LinearRegression().fit(df[['5k_1', '5k_2', '5k_3', '5k_4']], df['VDOT'])

# Get model predictions
plot_space = np.linspace(700, 1900, num=50)
vdots_1 = model_1.intercept_ + (plot_space * model_1.coef_[0])
vdots_2 = model_2.intercept_ + (plot_space * model_2.coef_[0]) + ((plot_space**2)*model_2.coef_[1])
vdots_3 = model_3.intercept_ + (plot_space * model_3.coef_[0]) + ((plot_space**2)*model_3.coef_[1]) + ((plot_space**3)*model_3.coef_[2])
vdots_4 = model_4.intercept_ + (plot_space * model_4.coef_[0]) + ((plot_space**2)*model_4.coef_[1]) + ((plot_space**3)*model_4.coef_[2]) + ((plot_space**4)*model_4.coef_[3])

# Plot true, and model predictions
df.plot(y='VDOT',
        x='5k Time',
        kind='scatter',
        grid=True,
        title='5k Times Against VDOT (with Multiple Regression Models)')
plt.xticks(ticks=[900, 1200, 1500, 1800],
           labels=['15:00', '20:00', '25:00', '30:00'])
plt.plot(plot_space, vdots_1, label='Power 1')
plt.plot(plot_space, vdots_2, label='Power 2')
plt.plot(plot_space, vdots_3, label='Power 3')
plt.plot(plot_space, vdots_4, label='Power 4')
plt.legend()
plt.savefig('../generated-notes/5k-models/multi-plot.png')

# Output scores for each model
print()
print('Model 1:', model_1.score(df[['5k_1']], df['VDOT']))
print('Model 2:', model_2.score(df[['5k_1', '5k_2']], df['VDOT']))
print('Model 3:', model_3.score(df[['5k_1', '5k_2', '5k_3']], df['VDOT']))
print('Model 4:', model_4.score(df[['5k_1', '5k_2', '5k_3', '5k_4']], df['VDOT']))

# Print coefs and intercept for model 4
print()
print('Model 4')
print('Coefs:    ', model_4.coef_)
print('Intercept:', model_4.intercept_)

####################
# These are helper functions created from the power 4 model

def fivek_time_to_vdot(time):
    c = 320.21840994212795
    m = [-5.85338453e-01,4.99386989e-04,-2.05665011e-07,3.29250289e-11]

    secs = str_time_to_num_time(time)
    vdot = c + (secs*m[0]) + ((secs**2)*m[1]) + ((secs**3)*m[2]) + ((secs**4)*m[3])
    return vdot

print()
print('20:00 to ', fivek_time_to_vdot('20:00'))
print('22:00 to ', fivek_time_to_vdot('22:00'))
print('24:00 to ', fivek_time_to_vdot('24:00'))
print('26:00 to ', fivek_time_to_vdot('26:00'))


import numpy as np
import pymc3
from scipy.stats import binom, beta

#3M1
grid = np.linspace(0.0, 1.0, 1000)
prior = np.ones(1000)

likelihood = binom.pmf(8, 15, p=grid)

posterior = likelihood * prior
posterior /= np.sum(posterior)

#3M2
np.random.seed(100)
samples = np.random.choice(grid, size=10000, replace=True, p=posterior)

print('2')
print(pymc3.stats.hpd(samples, 0.9))

#3M3
dummyData = binom.rvs(15, samples, size=samples.shape[0])
print('\n3')
print(np.mean(dummyData == 8))

#3M4
dummyData = binom.rvs(9, samples, size=samples.shape[0])
print('\n4')
print(np.mean(dummyData == 6))

#3M5
prior[grid < 0.5] = 0

posterior = likelihood * prior
posterior /= np.sum(posterior)

samples = np.random.choice(grid, size=10000, replace=True, p=posterior)
print('\n5')
print(pymc3.stats.hpd(samples, 0.9))

dummyData = binom.rvs(15, samples, size=samples.shape[0])
print(np.mean(dummyData == 8))

dummyData = binom.rvs(9, samples, size=samples.shape[0])
print(np.mean(dummyData == 6))

#3M6

N = 2500
s = int(np.round(8 * N / 15))
likelihood = binom.pmf(s, N, p=grid)

posterior = likelihood * prior
posterior /= np.sum(posterior)

samples = np.random.choice(grid, size=10000, replace=True, p=posterior)

interval = pymc3.stats.hpd(samples, 0.99)
print('\n6')
print('%d: %f' % (N, interval[1] - interval[0]))


from pylab import *
from scipy.integrate import quad;
from scipy.interpolate import interp1d

close('all')

# PDF of the standard normal distribution.
p = lambda t : exp(-t**2/2.0)/sqrt(2*pi);
# CDF of the standard normal distribution.
F = lambda x : (quad(p,-inf,x))[0];

# Take discrete points (x,F(x))
Ns = 40;
x = linspace(-7,7,Ns);
y = zeros(Ns)
for i in xrange(Ns):
	y[i] = F(x[i]);

plot(x,y,'r*')

# Interpolate F
Fint = interp1d(x,y);

plot(x,Fint(x),'g--')
legend(['(x,F(x))','Interpolation'],loc=0);

figure()

Finv = interp1d(y,x);
plot(x,Finv(Fint(x)),'b--',x,x,'r*-')
legend(['Finv(Fint(x))','y=x'],loc=0)

# Now let's sample from F!

# First, we need N samples from U[0,1]
N = 1e+6;
u = rand(N)

# Now, we need to calculate Finv(u), which will
# gives us the samples we want.
x = Finv(u);

print "Mean of samples : ", mean(x)
print "Variance of samples :", var(x)

# Let's make a histogram of what we got.

figure()
hist(x,normed=True)

# We need to compare with samples from the Standard Normal distribution.
un = randn(N);
hist(un,normed=True,color='red',alpha=0.6)

legend(['Samples with our method','"Real" samples'],loc=0)

show()


# coding: utf-8

# ## Exercises
#
# This will be a notebook for you to work through the exercises during the workshop. Feel free to work on these at whatever pace you feel works for you, but I encourage you to work together! Edit the title of this notebook with your name because I will ask you to upload your final notebook to our shared github repository at the end of this workshop.
#
# Feel free to google the documentation for numpy, matplotlib, etc.
#
# Don't forget to start by importing any libraries you need.

# In[2]:

# import your libraries here
import numpy as np
import pylab as plt

# ### Day 1
#
# #### Exercise 1
#
#    A. Create an array with 10 evenly spaced values in logspace ranging from 0.1 to 10,000.
#
#    B. Print the following values: The first value in the array, the final value in the array, and the range of 5th-8th values.
#
#    C. Append the numbers 10,001 and 10,002 (as floats) to the array. Make sure you define this!
#
#    D. Divide your new array by 2.
#
#    E. Reshape your array to be 3 x 4.
#
#    F. Multiply your array by itself.
#
#    G.  Print out the number of dimensions and the maximum value.

# In[5]:

# your solution here

print('A')
log_arr = np.logspace(-1, 4, 10)
print(log_arr)
print()

print('B')
print(log_arr[0], log_arr[-1], log_arr[4:8])

print()

print('C')
x = np.array([10001. , 10002. ])

new_log_arr = np.append(log_arr, x)
print(new_log_arr)
print()

print('D')
divide_by_2 = new_log_arr/2
print(divide_by_2)
print()

print('E')
reshaped_arr = divide_by_2.reshape((3,4))

print(reshaped_arr)
print()

print('F')
mult = reshaped_arr * reshaped_arr
print(mult)
print()

print('G')
print(mult.ndim, np.amax(mult))

# ### Day 2

# #### Exercise 1
#
#    A. Create an array containing the values 4, 0, 6, 5, 11, 14, 12, 14, 5, 16.
#    B. Create a 10x2 array of zeros.
#    C. Write a for loop that checks if each of the numbers in the first array squared is less than 100. If the statement is true, change that row of your zeros array to equal the number and its square. Hint: you can change the value of an array by stating "zerosarray[i] = [a number, a number squared]".
#    D. Print out the final version of your zeros array.
#
# Hint: should you loop over the elements of the array or the indices of the array?

# In[7]:

# your solutions here

#making my array
arr = np.array([4, 0, 6, 5, 11, 14, 12, 14, 5, 16])

#making my 10X2 array of zeros
zero_arr = np.zeros((10,2))

#going through the loop and finding the square values < 100
for i, val in enumerate(arr):

    if val**2 < 100:
        zero_arr[i] = [val, val**2]

print(zero_arr)

# #### Exercise 2
#
#    A. Write a function that takes an array of numbers and spits out the Gaussian distribution. Yes, there is a function for this in Python, but it's good to do this from scratch! This is the equation:
#
# $$ f(x) = \frac{1}{\sigma \sqrt{2\pi}} \exp{\frac{-(x - \mu)^2}{2\sigma^2}} $$
#
#     (Pi is built into numpy, so call it as np.pi.)
#
#    B. Call the function a few different times for different values of mu and sigma, between -10 < x < 10.
#
#    C. Plot each version, making sure they are differentiated with different colors and/or linestyles and include a legend. Btw, here's a list of the customizations available in matplotlib:
#
#     https://matplotlib.org/3.1.0/api/_as_gen/matplotlib.pyplot.plot.html
#
#     https://matplotlib.org/gallery/color/named_colors.html
#
#    D. Save your figure.
#
# If you have multiple lines with plt.plot(), Python will plot all of them together, unless you write plt.show() after each one. I want these all on one plot.

# In[24]:

# your solutions here
def Gauss(x, mu, sigma):
    '''
    This function calculates the Guassian distribution given x, mu, sigma

    Parameters
    -------------
    x: the range of x values you are interested in finding the Gaussian distribution
    mu: the average of the given distribution
    sigma: the standard deviation of the distribution

    Output:
    Gaussian distribution given the x, mu, and sigma you passed in

    '''
    #making a prefactor variable
    prefactor = 1/(sigma* np.sqrt(2*np.pi))
    #making the exponential part into its own variable
    exp = np.exp(-(x-mu)**2/(2*sigma**2))

    #returning the Gaussian
    return prefactor * exp

#making my x array
x = np.linspace(-10, 10, 500)

y1 = Gauss(x, 1, 1)
y2 = Gauss(x, 3, .5)
y3 = Gauss(x, -2, 4)
y4 = Gauss(x, 1.2, .3)
y5 = Gauss(x, -3.2, 2)

plt.figure(figsize = (14, 8))
plt.title('Gaussian Function', fontsize = 16)
plt.xlabel('x values', fontsize = 16)
plt.ylabel('y-values of Gaussian', fontsize = 16)

#yaxis goes from 0 to 1 since it sproperly normalized by the prefactor
plt.axis([x[0], x[-1], 0, 1])
plt.plot(x, y1, 'r-', label = r'$\mu$ = 1, $\sigma$ = 1')
plt.plot(x, y2, 'b--', label = r'$\mu$ = 3, $\sigma$ = .5')
plt.plot(x, y3, 'k*', label = r'$\mu$ = -2, $\sigma$ = 4')
plt.plot(x, y4, 'gs', label = r'$\mu$ = 1.2, $\sigma$ = 8')
plt.plot(x, y5, 'yo', label = r'$\mu$ = -3.2, $\sigma$ = 6.75')
plt.legend(loc = 'best')
plt.savefig('Gaussian_Plots.pdf')
plt.show()

# ### Day 3
#
# #### Exercise 1
#
# There is a file in this directory called "histogram_exercise.dat" which consists of of randomly generated samples from a Gaussian distribution with an unknown $\mu$ and $\sigma$. Using what you've learned about fitting data, load up this file using np.genfromtxt, fit a Gaussian curve to the data and plot both the curve and the histogram of the data. As always, label everything, play with the colors, and choose a judicious bin size.
#
# Hint: if you attempt to call a function from a library or package that hasn't been imported, you will get an error.

# In[5]:

from scipy.stats import norm

# In[6]:

# your solution here
gauss_data = np.loadtxt('histogram_exercise.dat')

# In[8]:

mu, sigma = norm.fit(gauss_data)

x = np.linspace(np.min(gauss_data), np.max(gauss_data), 1000)

gauss = norm.pdf(x, mu, sigma)

# In[21]:

plt.figure(figsize =(12, 12))
plt.title('Gauss and Gaussian Fit')
plt.plot(x, gauss, 'k', linewidth = 2, label= 'Gauss Fit')
plt.hist(gauss_data, color= 'yellow', normed=True, hatch='//', label='Gaussian Data')
plt.legend(loc='best')
plt.show()

# #### Exercise 2
#
# Create a 1D interpolation along these arrays. Plot both the data (as points) and the interpolation (as a dotted line). Also plot the value of the interpolated function at x=325. What does the function look like to you?

# In[22]:

from scipy.interpolate import interp1d

# In[24]:

x = np.array([0., 50., 100., 150., 200., 250., 300., 350., 400., 450., 500])
y = np.array([0., 7.071, 10., 12.247, 14.142, 15.811, 17.321, 18.708, 20., 21.213, 22.361])

# solution here

f = interp1d(x, y)

# In[34]:

xnew = np.linspace(0, 500, 1000)
plt.figure(figsize = (10,10))
plt.plot(x, y, 'ko', label = 'Data')
plt.plot(xnew, f(xnew), 'r--', label = 'Interpolation')
plt.plot(325, f(325), 'b*', label = 'x = 325', markersize = 15)
plt.legend(loc = 'best', frameon=False)
plt.show()

# In[1]:

from astropy import constants as const
import numpy as np
import matplotlib.pyplot as plt
from astropy.io import fits
import aplpy

# ### Day 4
#
# #### Exercise 1
#
# Let's practice some more plotting skills, now incorporating units.
#
# A. Write a function that takes an array of frequencies and spits out the Planck distribution. That's this equation:
#
# $$ B(\nu, T) = \frac{2h\nu^3/c^2}{e^{\frac{h\nu}{k_B T}} - 1} $$
#
# This requires you to use the Planck constant, the Boltzmann constant, and the speed of light from astropy. Make sure they are all in cgs.
#
# B. Plot your function in log-log space for T = 25, 50, and 300 K. The most sensible frequency range is about 10^5 to 10^15 Hz. Hint: if your units are correct, your peak values of B(T) should be on the order of 10^-10. Make sure everything is labelled.

# In[4]:

h = const.h.cgs
k = const.k_B.cgs
c = const.c.cgs.value
print(h)
print(k)
print(c)

# In[8]:

h = const.h.cgs.value
k = const.k_B.cgs.value
c = const.c.cgs.value

# solution here
def blackbody(nu, T):

    numerator = (2 * h * nu**3)/c**2
    denom = np.exp((h * nu)/(k * T)) - 1

    return numerator/denom

nu = np.linspace(1e5, 1e15, 1e5)
T = [25, 50, 300]

plt.figure(figsize = (10,10))
plt.xlabel('Frequency [Hz]', fontsize = 16)
plt.ylabel('Specific Intensity', fontsize = 16)
plt.title('Planck Distribution', fontsize = 16)

for i in T:
    plt.loglog(nu, blackbody(nu, i), label = str(i) + ' K')

plt.legend(loc='best', fontsize = 14, frameon=False)
plt.show()

# #### Exercise 2
#
# Let's put everything together now! Here's a link to the full documentation for FITSFigure, which will tell you all of the customizable options: http://aplpy.readthedocs.io/en/stable/api/aplpy.FITSFigure.html. Let's create a nice plot of M51 with a background optical image and X-ray contours overplotted.
#
# The data came from here if you're interested: http://chandra.harvard.edu/photo/openFITS/multiwavelength_data.html
#
# A. Using astropy, open the X-RAY data (m51_xray.fits). Flatten the data array and find its standard deviation, and call it sigma.
#
# B. Using aplpy, plot a colorscale image of the OPTICAL data. Choose a colormap that is visually appealing (list of them here: https://matplotlib.org/2.0.2/examples/color/colormaps_reference.html). Show the colorbar.
#
# C. Plot the X-ray data as contours above the optical image. Make the contours spring green with 80% opacity and dotted lines. Make the levels go from 2$\sigma$ to 10$\sigma$ in steps of 2$\sigma$. (It might be easier to define the levels array before show_contours, and set levels=levels.)

# In[20]:

# solution here
data = fits.getdata('m51_xray.fits')

flat_data = data.flatten()

sigma = np.std(flat_data)

# In[35]:

galaxy = aplpy.FITSFigure('m51_optical_B.fits')
galaxy.show_colorscale(cmap='cubehelix')
galaxy.show_colorbar()

plt.show()

# In[21]:

2*sigma

# In[29]:

levels = np.linspace(2*sigma, 10*sigma, num = 5)
levels[1]-levels[0]

# In[36]:

levels = np.linspace(2*sigma, 10*sigma, num = ((8*sigma)/(2*sigma)))

galaxy = aplpy.FITSFigure('m51_optical_B.fits')
galaxy.show_colorscale(cmap='cubehelix')
galaxy.show_contour('m51_xray.fits', linestyle= 'dotted', colors = 'springgreen', alpha = .8, levels = levels)
#galaxy.show_colorbar()

plt.show()


import numpy as np
from numpy import array
from numpy import mean
from numpy.linalg import eig

C_1 = array([[1, 2], [2, 3], [3, 3], [4, 5], [5, 5]])
C_2 = array([[1, 0], [2, 1], [3, 1], [3, 2], [5, 3], [6, 5]])
print("We have the data:")
print("Class C1:\n", C_1)
print("Class C1:\n", C_2)
M_1 = mean(C_1.T, axis=1)
M_2 = mean(C_2.T, axis=1)
print("Step1: Let's compute the mean for each class:")
print("Mean of class C1: mu1 = \n", M_1)
print("Mean of class C2: mu2 = \n", M_2)
S_1 = (len(C_1) - 1) * np.cov(C_1.T)
S_2 = (len(C_2) - 1) * np.cov(C_2.T)
print("Step2: Let's compute the scatter matrices for each class:")
print("Scatter matrix of class C1: S1 = \n", S_1)
print("Scatter matrix of class C2: S2 = \n", S_2)
S_W = S_1 + S_2
print("Step3: Within the class scatter S_W = S_1 + S_2")
print("S_W = \n", S_W)
S_W_I = np.linalg.inv(S_W)
print("Step4: Let's compute the inverse of S_W")
print("S_W_I = \n", S_W_I)
V = np.matmul(S_W_I, (M_1 - M_2))
print("Step5: The optimal line direction v = S_W_I(mu1-mu2)")
print("v = \n", V)


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

########
#Name: Conner Carnahan
#ID: 1614309
#Email: carna104@mail.chapman.edu
#Class: PHYS220
#Date: Oct 16, 2018
########

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

@np.vectorize
def Sn(T,t,n):
    """Sn(float T,float t,int n): Returns a value computed by a sum of sin functions in accordance with the Fourier series expansion of sign(x)"""
    if (abs(t) > T/2):
        print("t should be within the range -T/2, T/2")
        pass
    K = np.arange(1,n+1)
    K = np.divide(4,np.pi*(2*K-1))
    SinPeriods = np.divide(2*np.pi*(2*np.arange(1,n+1)-1),T)
    value = np.sum(K*np.sin(SinPeriods*t))
    return value

@np.vectorize
def f(T,t):
    """f(float T, float t): Returns a value that is the sign of the value inputed
       if t < 0 sign(t) = -1
       if t > 0 sign(t) = 1
       if t = 0 sign(t) = 0"""
    if (abs(t) > T/2):
        print("t should be between T/2")
        pass
    return np.sign(t)

def Snarray(T,n,K = 300):
    """Snarray(T float, n int, K = 300 int): returns numpy array, Generates an array of values for K values of t in [-T/2,T/2] of the summed sines which approximate sign(x)"""
    Time = np.linspace(-T/2,T/2,K)
    return Sn(T,Time,n)

def farray(T,K = 300):
    """farray(T float, K = 300 int): returns numpy array of values evaluated by sign(x) for equally spaced K values of x in [-T/2,T/2]"""
    Time = np.linspace(-T/2,T/2,K)
    return f(T,Time)

def timespace(T,K = 300):
    """timespace(T float, K = 300 int), returns numpy array of K equally spaced values in [-T/2,T/2]"""
    return np.linspace(-T/2,T/2,K)

### DO NOT USE (OUT OF ORDER)
def buildallplots(alpha):
    """DON'T DO IT ONLY A PROTOTYPE
    args: alpha (float),
       returns null
       This is a helper function that takes in a float, alpha,
       and generates a sequence of partial Fourier Sums that approximate the sign function"""
    T = alpha*2*np.pi
    F1Array = ss.Snarray(T,1)
    F3Array = ss.Snarray(T,3)
    F5Array = ss.Snarray(T,5)
    F10Array = ss.Snarray(T,10)
    F30Array = ss.Snarray(T,30)
    F100Array = ss.Snarray(T,100)
    FuncArray = ss.farray(T)
    Time = ss.timespace(T)
###


from numpy.linalg import norm
from math import sin, cos, asin, acos, atan2, pi, degrees

class Finesse:
    @staticmethod
    def forward_pack(lengths, angles):
        """
        Computes the forward kinematics for the legs of DOG.
        :param lengths: An array of lengths (l1, l2).
        :param angles: An array of angles (theta1, theta2, theta3).
        :return: (x3, y3, z3)
        """

        l1, l2 = lengths
        theta1, theta2, theta3 = angles

        x1, y1, z1 = 0, 0, 0

        x2 = -l1 * sin(theta1) * cos(theta2)
        y2 = l1 * sin(theta2)
        z2 = -l1 * cos(theta1) * cos(theta2)

        x3 = x2 - l2 * cos(theta1) * sin(theta3) - l2 * cos(theta2) * cos(theta3) * sin(theta1)
        y3 = y2 + l2 * cos(theta3) * sin(theta2)
        z3 = z2 + l2 * sin(theta1) * sin(theta3) - l2 * cos(theta1) * cos(theta2) * cos(theta3)

        return x3, y3, z3

    @staticmethod
    def inverse_pack(lengths, target, a2=False, a3=False, deg=True):
        """
        Computes the inverse kinematics for the legs of DOG and Alpha
        For the back legs of Alpha, pass 0 for y.
        :param lengths: An array of lengths (l1, l2).
        :param target: The coordinate of the target (x, y, z).
        :param a2: Returns an alternate solution for theta2.
        :param a3: Returns an alternate solution for theta3.
        :param deg: Return the result in degrees if True and radians otherwise.
        :return: (theta1, theta2, theta3)
        """

        if lengths is None or target is None:
            raise ValueError

        l1, l2 = lengths
        x, y, z = target
        dist = norm(target)

        if dist > sum(lengths):
            raise ValueError

        # theta3 *= -1
        # Returns [0, 180]. +/- expands solution to [-180, 180].
        theta3 = (l1 ** 2 + l2 ** 2 - dist ** 2) / (2 * l1 * l2)
        theta3 = round(theta3, 13)
        theta3 = acos(theta3) - pi
        if a3:
            theta3 *= -1

        # theta2 = (pi - theta2)
        # Returns [-90, 90]. (pi - theta2) expands solution to [-180, 180].
        theta2 = y / (l1 + l2 * cos(theta3))
        theta2 = round(theta2, 13)
        theta2 = asin(theta2)
        if a2:
            theta2 = pi - theta2

        # theta1 -= 2 * pi
        # Sometimes (theta1 - 2 * pi). Doesn't matter. Either is cool.
        theta1 = atan2(z, -x) + atan2((l1 + l2 * cos(theta3)) * cos(theta2), l2 * sin(theta3))

        if deg:
            return degrees(theta1), degrees(theta2), degrees(theta3)
        else:
            return theta1, theta2, theta3


'''
    Recursive multiplication algorithms.
'''

import pandas as pd
import numpy as np
import timeit

def pad_inputs_(x, y):
    '''Left 0-pad inputs to have equal number of digits.'''
    if len(x) > len(y):
        y = '0' * (len(x) - len(y)) + y
    elif len(y) > len(x):
        x = '0' * (len(y) - len(x)) + x
    return x, y

def split_input_(s):
    '''Splits input digits in half.'''
    split_point = len(s) // 2
    return s[:split_point], s[split_point:]

def rec_int_mult_(x, y):
    '''Multiply two integers using a recrusive approach.'''
    # Pad inputs to be the same length
    x, y = pad_inputs_(x, y)

    # Check for base case
    n = len(x)
    if n == 1:
        return int(x) * int(y)

    # Split inputs
    a, b = split_input_(x)
    c, d = split_input_(y)

    # Recursively compute pair products
    ac = rec_int_mult_(a, c)
    ad = rec_int_mult_(a, d)
    bc = rec_int_mult_(b, c)
    bd = rec_int_mult_(b, d)

    # Combine results
    if n % 2 == 1: # Handle odd-length strings
        n += 1
    return ac*10**(n) + (ad + bc)*10**(n//2) + bd

def rec_int_mult(x, y):
    '''Multiply two integers using a recursive approach.

    Parameters
    ----------
    x : int
        The left operand for integer multiplication.
    y : int
        The right operand for integer multiplication.
    Returns
    -------
    int
        The result of multiplying x and y.

    Based off pseudocode from Algorithms Illuminated Part 1.
    '''
    # This is a wrapper to cast the inputs to strings for the first call
    x = str(x)
    y = str(y)
    return rec_int_mult_(x, y)

def karatsuba_(x, y):
    '''Multiply two integers using Karatsuba multiplication.'''
    # Pad inputs to be the same length
    x, y = pad_inputs_(x, y)

    # Check for base case
    n = len(x)
    if n == 1:
        return int(x) * int(y)

    # Split inputs
    a, b = split_input_(x)
    c, d = split_input_(y)

    # Compute p and q
    p = str(int(a) + int(b))
    q = str(int(c) + int(d))

    # Recursively compute pair products
    ac = karatsuba_(a, c)
    bd = karatsuba_(b, d)
    pq = karatsuba_(p, q)

    # Combine results
    adbc = pq - ac - bd
    if n % 2 == 1: # Handle odd-length strings
        n += 1
    return ac*10**(n) + (adbc)*10**(n//2) + bd

def karatsuba(x, y):
    '''Multiply two integers using Karatsuba multiplication.

    Parameters
    ----------
    x : int
        The left operand for integer multiplication.
    y : int
        The right operand for integer multiplication.
    Returns
    -------
    int
        The result of multiplying x and y.

    Based off pseudocode from Algorithms Illuminated Part 1.
    '''
    # This is a wrapper to cast the inputs to strings for the first call
    x = str(x)
    y = str(y)
    return karatsuba_(x, y)

def built_in_multiply(x, y):
    '''Applies the built-in multiplication operator '''
    return x * y

def get_random_input(n):
    '''Returns random integer with specified number of digits.'''
    return int(''.join([str(digit) for digit in np.random.randint(0,10,n)]))

def get_setup(algorithm_name, n):
    s = f"from __main__ import {algorithm_name}; import numpy as np;"
    s += f"x = int(''.join([str(digit) for digit in np.random.randint(0,10,{n})]));"
    s += f"y = int(''.join([str(digit) for digit in np.random.randint(0,10,{n})]));"
    return s

if __name__ == '__main__':
    # First, correctness tests involving varying length combinations
    algorithms = {'rec_int_mult': rec_int_mult, 'karatsuba': karatsuba}
    digit_range = (1,20) # Range of number of digits to test
    for algorithm_name, algorithm in algorithms.items():
        print(f'\nRunning correctness tests for {algorithm_name} with number of digits from {digit_range[0]} to {digit_range[1]}...')
        num_tested = 0
        num_passed = 0
        failed_inputs = []
        # Tests all permutations of digit ranges with built-in operator as reference
        for x_digits in range(min_digits, max_digits):
            for y_digits in range(min_digits, max_digits):
                x, y = get_random_input(x_digits), get_random_input(y_digits)
                result = algorithm(x, y)
                if result == x * y:
                    num_passed += 1
                else:
                    failed_inputs.append((x, y))
                num_tested += 1
        print(f'Results: {num_passed} passed out of {num_tested} tests.')
        if num_tested > num_passed:
            print(f'Failed input sets:')
            for inputs in failed_inputs:
                print(inputs)

    # Second, timing tests for various input sizes
    algorithms['built_in_multiply'] = built_in_multiply
    results = pd.DataFrame(data={'n':[40, 80, 160, 320]})
    for algorithm_name, algorithm in algorithms.items():
        print(f'\nRunning timing tests for {algorithm_name}...')
        temp_results = []
        for n in results['n'].values:
            n = int(n)
            temp_results.append(np.round(timeit.timeit(f'{algorithm_name}(x, y)', setup=get_setup(algorithm_name, n), number=1), 4))
        results[algorithm_name] = temp_results
    print('Timing tests complete.')
    print(results.head(results.shape[0]))


# Load modules
from __future__ import print_function
import os
import pandas as pd
import numpy as np
from matplotlib import pyplot as plt

# read the data from into a pandas.DataFrame
wisc_emp = pd.read_csv("datasets/wisconsin-employment-time-series.csv")

# Let's find out the shape of the DataFrame
print("Shape of the DataFrame:", wisc_emp.shape)

# Let's see first 10 rows of it
wisc_emp.head()

# plot the wisconsin employment dataset
wisc_emp.plot()

# Capture seasonality component
def initialize_T(x, seasonLength):
    total = 0.0
    for i in range(seasonLength):
        total += float(x[i + seasonLength] - x[i]) / seasonLength
    return total

initialize_T(wisc_emp["Employment"], 12)

# Initialize seasonal trend
def initialize_seasonalilty(x, seasonLength):
    seasons = {}
    seasonsMean = []
    num_season = int(len(x) / seasonLength)
    # Compute season average
    for i in range(num_season):
        seasonsMean.append(
            sum(x[seasonLength * i : seasonLength * i + seasonLength])
            / float(seasonLength)
        )

    # compute season intial values
    for i in range(seasonLength):
        tot = 0.0
        for j in range(num_season):
            tot += x[seasonLength * j + i] - seasonsMean[j]
        seasons[i] = tot / num_season
    return seasons

initialize_seasonalilty(wisc_emp["Employment"], 12)

# Triple Exponential Smoothing Forecast
def triple_exp_smoothing(x, seasonLength, alpha, beta, gamma, h):
    yhat = []
    S = initialize_seasonalilty(x, seasonLength)
    for i in range(len(x) + h):
        if i == 0:
            F = x[0]
            T = initialize_T(x, seasonLength)
            yhat.append(x[0])
            continue
        if i >= len(x):
            m = i - len(x) + 1
            yhat.append((F + m * T) + S[i % seasonLength])
        else:
            obsval = x[i]
            F_last, F = (
                F,
                alpha * (obsval - S[i % seasonLength]) + (1 - alpha) * (F + T),
            )
            T = beta * (F - F_last) + (1 - beta) * T
            S[i % seasonLength] = (
                gamma * (obsval - F) + (1 - gamma) * S[i % seasonLength]
            )
            yhat.append(F + T + S[i % seasonLength])
    return yhat

# Triple exponential smoothing
wisc_emp["TES"] = triple_exp_smoothing(wisc_emp["Employment"], 12, 0.4, 0.6, 0.2, 0)

### Plot Single Exponential Smoothing forecasted value
fig = plt.figure(figsize=(5.5, 5.5))
ax = fig.add_subplot(2, 1, 1)
wisc_emp["Employment"].plot(ax=ax)
ax.set_title("Beer Production")
ax = fig.add_subplot(2, 1, 2)
wisc_emp["TES"].plot(ax=ax, color="r")
ax.set_title("Triple Smoothing Forecast")
plt.savefig("plots/ch2/B07887_03_14.png", format="png", dpi=300)

time series regression/autocorelation, mov avg etc/tripleExponentialSmoothing.py


# find the inverse of a matrix using Gaussian elimination

import numpy

def inverse(AInput):
    """ return the inverse of AInput """

    A = AInput.copy()

    N = len(A[:,0])

    # A is square, with each dimension of length N
    if not (A.shape[0] == A.shape[1]):
        print "ERROR: A should be square"
        return None

    # create an identity matrix
    I = numpy.identity(N)

    # allocation for the inverse
    Ainv = numpy.zeros((N,N), dtype=A.dtype)

    # find the scale factors for each row -- this is used when pivoting
    scales = numpy.max(numpy.abs(A), 1)

    # keep track of the number of times we swapped rows
    numRowSwap = 0

    # we are essentially doing Gaussian elimination, but with A Ainv = I
    # each column of I represents a separate righthand side to an Ax = b
    # linear system

    # main loop over rows
    for k in range(N):

        # find the pivot row based on the size of column k -- only consider
        # the rows beyond the current row
        rowMax = numpy.argmax(A[k:, k]/scales[k:])
        if (k > 0): rowMax += k  # we sliced A from k:, correct for total rows

        # swap the row with the largest scaled element in the current column
        # with the current row (pivot) -- do this with b too!
        if not rowMax == k:
            A[[k, rowMax],:] = A[[rowMax, k],:]
            I[[k, rowMax],:] = I[[rowMax, k],:]
            numRowSwap += 1

        # do the forward-elimination for all rows below the current
        for i in range(k+1, N):
            coeff = A[i,k]/A[k,k]

            for j in range(k+1, N):
                A[i,j] += -A[k,j]*coeff

            A[i,k] = 0.0
            I[i,:] += -coeff*I[k,:]

    # back-substitution -- once for each column in the I matrix

    for c in range(N):

        # last solution is easy
        Ainv[N-1,c] = I[N-1,c]/A[N-1,N-1]

        for i in reversed(range(N-1)):
            sum = I[i,c]
            for j in range(i+1,N):
                sum += -A[i,j]*Ainv[j,c]
            Ainv[i,c] = sum/A[i,i]

    # determinant
    det = numpy.prod(numpy.diagonal(A))*(-1.0)**numRowSwap

    return Ainv

# output: numpy.savetxt("test.out", a, fmt="%5.2f", delimiter="  ")
# convert -font Courier-New-Regular -pointsize 20 text:test.out test.png

A = numpy.array([ [4, 3, 4, 10], [2, -7, 3, 0], [-2, 11, 1, 3], [3, -4, 0, 2] ], dtype=numpy.float64)
Ainv = inverse(A)
print "A . Ainv = \n", numpy.dot(A, Ainv)
print" Ainv = \n", Ainv

print " "

A = numpy.array([ [0, 1, 1], [1, 1, 0], [1, 0, 1] ], dtype=numpy.float64)
Ainv = inverse(A)
print "A . Ainv = \n", numpy.dot(A, Ainv)

print " "

A = numpy.array([ [0, 0, 0, 4],
                  [0, 0, 3, 0],
                  [5, 6, 7, 8],
                  [0, 4, 3, 2] ], dtype=numpy.float64)
Ainv = inverse(A)
print "A . Ainv = \n", numpy.dot(A, Ainv)


"""
3D version of approx2D.py.
Numerical integration only.
"""
import sympy as sym
import numpy as np
import scipy.integrate

def least_squares(f, psi, Omega):
    """
    Given a function f(x,y,z) on a rectangular domain
    Omega=[[xmin,xmax],[ymin,ymax],[zmin,zmax]],
    return the best approximation to f in the space V
    spanned by the functions in the list psi.
    f and psi are symbolic (sympy) expressions, but will
    be converted to numeric functions for faster integration.
    """
    N = len(psi) - 1
    A = np.zeros((N+1, N+1))
    b = np.zeros(N+1)
    x, y, z = sym.symbols('x y z')
    f = sym.lambdify([x, y, z], f, modules='numpy')
    psi_sym = psi[:]  # take a copy, needed for forming u later
    psi = [sym.lambdify([x, y, z], psi[i]) for i in range(len(psi))]

    print('...evaluating matrix...')
    for i in range(N+1):
        for j in range(i, N+1):
            print(('(%d,%d)' % (i, j)))

            integrand = lambda x, y, z: psi[i](x,y,z)*psi[j](x,y,z)
            I, err = scipy.integrate.nquad(
                integrand,
                [[Omega[0][0], Omega[0][1]],
                 [Omega[1][0], Omega[1][1]],
                 [Omega[2][0], Omega[2][1]]])
            A[i,j] = A[j,i] = I
        integrand = lambda x, y, z: psi[i](x,y,z)*f(x,y,z)
        I, err = scipy.integrate.nquad(
            integrand,
            [[Omega[0][0], Omega[0][1]],
             [Omega[1][0], Omega[1][1]],
             [Omega[2][0], Omega[2][1]]])
        b[i] = I
    print()
    c = np.linalg.solve(A, b)
    if N <= 10:
        print(('A:\n', A, '\nb:\n', b))
        print(('coeff:', c))
    u = sum(c[i]*psi_sym[i] for i in range(len(psi_sym)))
    print(('approximation:', u))
    return u, c

def sine_basis(Nx, Ny, Nz):
    """
    Compute basis sin((p+1)*pi*x)*sin((q+1)*pi*y)*sin((r+1)*pi*z),
    p=0,...,Nx, q=0,...,Ny, r=0,...,Nz.
    """
    x, y, z = sym.symbols('x y z')
    psi = []
    for r in range(0, Nz+1):
        for q in range(0, Ny+1):
            for p in range(0, Nx+1):
                s = sym.sin((p+1)*sym.pi*x)*\
                    sym.sin((q+1)*sym.pi*y)*sym.sin((r+1)*sym.pi*z)
                psi.append(s)
    return psi

def test_least_squares():
    # Use sine functions
    x, y, z = sym.symbols('x y z')
    N = 1  # (N+1)**3 = 8 basis functions
    psi = sine_basis(N, N, N)
    f_coeff = [0]*len(psi)
    f_coeff[3] = 2
    f_coeff[4] = 3
    f = sum(f_coeff[i]*psi[i] for i in range(len(psi)))
    # Check that u exactly reproduces f
    u, c = least_squares(f, psi, Omega=[[0,1], [0,1], [0,1]])
    diff = np.abs(np.array(c) - np.array(f_coeff)).max()
    print(('diff:', diff))
    tol = 1E-15
    assert diff < tol

if __name__ == '__main__':
    import time
    t0 = time.clock()
    test_least_squares()


import numpy as np;

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

ar=np.array([(1,2,3),(3,4,5)],dtype=float)
# print(ar)

ar = np.array([(1, 2, 3), (3, 4, 5),(6,7,8)], dtype=float)

# print(ar)

#Creating Zero
print(np.zeros((2,3)))

print(np.ones((3,3),dtype=np.int16))

print(np.arange(2,10,2))

print(np.linspace(1,10,10))

print(ar.T) #Transpose

arT=ar.T

#Dot mul
print(ar.dot(arT))

""" Determinant of upper triangle or diagnal matrix is product of diagnal element """

a = np.array([(2, 3, 4), (0, 2, 5), (0, 0, 2)])
# a
# array([[2, 3, 4],
#        [0, 2, 5],
#        [0, 0, 2]])
print(np.linalg.det(a))
# 7.999999999999998

""" Determinant of row exhanged matrix will change the sign """

a=np.array([(2, 3, 4), (0, 0, 2), (0, 2, 5)])
print(np.linalg.det(a))
# - 7.999999999999998

""" Determinant of identiy matrix is 1 """
a = np.array([(1,0,0), (0, 1, 0), (0, 0,1)])
print(np.linalg.det(a))
# 1