# ポアソン分布

# 利用するライブラリ
import numpy as np
from scipy.stats import poisson # ポアソン分布
from scipy.special import gamma, loggamma # ガンマ関数, 対数ガンマ関数
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation

#%%

### 確率の計算

# パラメータを指定
lmd = 4.0

# 確率変数の値を指定
x = 2.0

# 定義式により確率を計算
prob = lmd**x / gamma(x + 1.0) * np.exp(-lmd)
print(prob)

# 対数をとった定義式により確率を計算
log_prob = x * np.log(lmd) - loggamma(x + 1.0) - lmd
prob = np.exp(log_prob)
print(prob, log_prob)

# ポアソン分布の関数により確率を計算
prob = poisson.pmf(k=x, mu=lmd)
print(prob)

# ポアソン分布の対数をとった関数により確率を計算
log_prob = poisson.logpmf(k=x, mu=lmd)
prob = np.exp(log_prob)
print(prob, log_prob)

#%%

### 統計量の計算

# パラメータを指定
lmd = 4.0

# 計算式により平均を計算
E_x = lmd
print(E_x)

# 計算式により分散を計算
V_x = lmd
print(V_x)

# ポアソン分布の関数により平均を計算
E_x = poisson.mean(mu=lmd)
print(E_x)

# ポアソン分布の関数により分散を計算
V_x = poisson.var(mu=lmd)
print(V_x)

#%%

### 分布の可視化

## 分布の計算

# パラメータを指定
lmd = 4.0

# 作図用のxの点を作成
x_vals = np.arange(np.ceil(lmd) * 4.0)

# ポアソン分布を計算
probability = poisson.pmf(k=x_vals, mu=lmd)

#%%

## 分布の作図

# ポアソン分布を作図
plt.figure(figsize=(12, 9)) # 図の設定
plt.bar(x=x_vals, height=probability, color='#00A968') # 棒グラフ
plt.xlabel('x') # x軸ラベル
plt.ylabel('probability') # y軸ラベル
plt.suptitle('Poisson Distribution', fontsize=20) # 全体のタイトル
plt.title('$\lambda=' + str(lmd) + '$', loc='left') # タイトル
plt.xticks(ticks=x_vals) # x軸目盛
plt.grid() # グリッド線
plt.show() # 描画

#%%

# 統計量を計算
E_x = lmd
s_x = np.sqrt(lmd)

# 統計量を重ねたポアソン分布を作図
plt.figure(figsize=(12, 9)) # 図の設定
plt.bar(x=x_vals, height=probability, color='#00A968') # 分布
plt.vlines(x=E_x, ymin=0.0, ymax=probability.max(), color='orange', linewidth=2.5, linestyle='--', label='$E[x]$') # 平均
plt.vlines(x=E_x - s_x, ymin=0.0, ymax=probability.max(), color='orange', linewidth=2.5, linestyle=':', label='$E[x] \pm \\sqrt{V[x]}$') # 平均 - 標準偏差
plt.vlines(x=E_x + s_x, ymin=0.0, ymax=probability.max(), color='orange', linewidth=2.5, linestyle=':') # 平均 + 標準偏差
plt.xlabel('x') # x軸ラベル
plt.ylabel('probability') # y軸ラベル
plt.suptitle('Poisson Distribution', fontsize=20)# 全体のタイトル
plt.title('$\lambda=' + str(lmd) + '$', loc='left') # タイトル
plt.xticks(ticks=x_vals) # x軸目盛
plt.legend() # 凡例
plt.grid() # グリッド線
plt.show() # 描画

#%%

### パラメータと分布の形状の関係

# lambdaとして利用する値を指定
lambda_vals = np.arange(start=0.0, stop=10.1, step=0.1)
print(len(lambda_vals)) # フレーム数

# 作図用のxの点を作成
x_vals = np.arange(np.ceil(lambda_vals.max()) * 2.0)

# y軸(確率)の最大値を設定
prob_max = np.max(poisson.pmf(k=x_vals, mu=lambda_vals.min())) + 0.1
#prob_max = 0.5

# 図を初期化
fig = plt.figure(figsize=(12, 9)) # 図の設定
fig.suptitle('Poisson Distribution', fontsize=20)# 全体のタイトル

# 作図処理を関数として定義
def update(i):
    # 前フレームのグラフを初期化
    plt.cla()

    # i回目のパラメータを取得
    lmd = lambda_vals[i]

    # ポアソン分布を計算
    probability = poisson.pmf(k=x_vals, mu=lmd)

    # ポアソン分布を作図
    plt.bar(x=x_vals, height=probability, color='#00A968') # 棒グラフ
    plt.xlabel('x') # x軸ラベル
    plt.ylabel('probability') # y軸ラベル
    plt.title('$\lambda=' + str(np.round(lmd, 1)) + '$', loc='left') # タイトル
    plt.xticks(ticks=x_vals) # x軸目盛
    plt.grid() # グリッド線
    plt.ylim(ymin=0.0, ymax=prob_max) # y軸の表示範囲

# gif画像を作成
anime_prob = FuncAnimation(fig, update, frames=len(lambda_vals), interval=100)

# gif画像を保存
anime_prob.save('ProbabilityDistribution/Poisson_prob.gif')

#%%

### 乱数の生成

## 乱数の生成

# パラメータを指定
lmd = 4.0

# データ数(サンプルサイズ)を指定
N = 1000

# ポアソン分布に従う乱数を生成
x_n = np.random.poisson(lam=lmd, size=N)

# 作図用のxの点を作成
x_vals = np.arange(x_n.max() + 5.0)

# 乱数を集計
frequency = np.array([np.sum(x_n == m) for m in x_vals])

# ポアソン分布を計算
probability = poisson.pmf(k=x_vals, mu=lmd)

#%%

## 乱数の可視化

# サンプルのヒストグラムを作成
plt.figure(figsize=(12, 9)) # 図の設定
plt.bar(x=x_vals, height=frequency, color='#00A968') # ヒストグラム
plt.xlabel('x') # x軸ラベル
plt.ylabel('frequency') # y軸ラベル
plt.suptitle('Poisson Distribution', fontsize=20)# 全体のタイトル
plt.title('$\lambda=' + str(lmd) + ', N=' + str(N) +
          '=(' + ', '.join([str(f) for f in frequency]) + ')$', loc='left') # タイトル
plt.xticks(ticks=x_vals) # x軸目盛
plt.grid() # グリッド線
plt.show() # 描画

#%%

# サンプルの構成比を作図
plt.figure(figsize=(12, 9)) # 図の設定
plt.bar(x=x_vals, height=probability, color='white', edgecolor='green', linestyle='--') # 元の分布
plt.bar(x=x_vals, height=frequency / N, color='#00A968', alpha=0.8) # 構成比
plt.xlabel('x') # x軸ラベル
plt.ylabel('proportion') # y軸ラベル
plt.suptitle('Poisson Distribution', fontsize=20)# 全体のタイトル
plt.title('$\lambda=' + str(lmd) + ', N=' + str(N) +
          '=(' + ', '.join([str(f) for f in frequency]) + ')$', loc='left') # タイトル
plt.xticks(ticks=x_vals) # x軸目盛
plt.grid() # グリッド線
plt.show() # 描画

#%%

## アニメーションによる可視化:(頻度)

# フレーム数を指定
N_frame = 100

# 図を初期化
fig = plt.figure(figsize=(12, 9)) # 図の設定
fig.suptitle('Poisson Distribution', fontsize=20)# 全体のタイトル

# y軸(頻度)の最大値を設定
freq_max = np.max([np.sum(x_n[:N_frame] == m) for m in x_vals]) + 1.0

# 作図処理を関数として定義
def update(n):
    # 前フレームのグラフを初期化
    plt.cla()

    # n個の乱数を集計
    frequency = np.array([np.sum(x_n[:(n+1)] == m) for m in x_vals])

    # サンプルのヒストグラムを作成
    plt.bar(x=x_vals, height=frequency, color='#00A968', zorder=1) # ヒストグラム
    plt.scatter(x=x_n[n], y=0.0, s=100, c='orange', zorder=2) # サンプル
    plt.xlabel('x') # x軸ラベル
    plt.ylabel('frequency') # y軸ラベル
    plt.title('$\lambda=' + str(lmd) + ', N=' + str(n + 1) +
              '=(' + ', '.join([str(f) for f in frequency]) + ')$', loc='left') # タイトル
    plt.xticks(ticks=x_vals) # x軸目盛
    plt.grid() # グリッド線
    plt.ylim(ymin=-0.5, ymax=freq_max) # y軸の表示範囲

# gif画像を作成
anime_freq = FuncAnimation(fig, update, frames=N_frame, interval=100)

# gif画像を保存
anime_freq.save('ProbabilityDistribution/Poisson_freq.gif')

#%%

## アニメーションによる可視化:(構成比)

# フレーム数を指定
N_frame = 100

# 図を初期化
fig = plt.figure(figsize=(12, 9)) # 図の設定
fig.suptitle('Poisson Distribution', fontsize=20)# 全体のタイトル

# y軸(割合)の最大値を設定
prop_max = np.max([np.sum(x_n[:N_frame] == m) for m in x_vals]) / N_frame + 0.1

# 作図処理を関数として定義
def update(n):
    # 前フレームのグラフを初期化
    plt.cla()

    # n個の乱数を集計
    frequency = np.array([np.sum(x_n[:(n+1)] == m) for m in x_vals])

    # サンプルのヒストグラムを作成
    plt.bar(x=x_vals, height=probability, color='white', edgecolor='green', linestyle='--', zorder=1) # 元の分布
    plt.bar(x=x_vals, height=frequency / (n + 1), color='#00A968', alpha=0.8, zorder=2) # 構成比
    plt.scatter(x=x_n[n], y=0.0, s=100, c='orange', zorder=3) # サンプル
    plt.xlabel('x') # x軸ラベル
    plt.ylabel('proportion') # y軸ラベル
    plt.title('$\lambda=' + str(lmd) + ', N=' + str(n + 1) +
              '=(' + ', '.join([str(f) for f in frequency]) + ')$', loc='left') # タイトル
    plt.xticks(ticks=x_vals) # x軸目盛
    plt.grid() # グリッド線
    plt.ylim(ymin=-0.01, ymax=prop_max) # y軸の表示範囲

# gif画像を作成
anime_prop = FuncAnimation(fig, update, frames=N_frame, interval=100)

# gif画像を保存
anime_prop.save('ProbabilityDistribution/Poisson_prop.gif')

#%%


import numpy as np
n_array = np.array([[1, 2, 3],
                    [4, 5, 6],
                    [7, 8, 9]])
print("Numpy Matrix is:")
trace = np.trace(n_array)
print("\nTrace of given 3X3 matrix:")
print(trace)

#15 (trace-sum of diagonal elements)


# encoding: utf-8
import numpy as np

# x = np.array([1.0,2.0,3.0])
# print(x)
# type(x)

x = np.array([1.0, 2.0, 3.0])
y = np.array([2.0, 4.0, 6.0])
print(x + y)
print(x - y)
print(x * y)
print(x / y)
print(x / 2)
# x 和 y 的元素个数要相同，不然会报错

# Numpy的N维数组
A = np.array([[1, 2], [3, 4]])
print(A)
print(A.shape)  # 矩阵的形状
print(A.dtype)  # 矩阵元素的数据类型

B = np.array([[3, 0], [0, 6]])
print(A + B)
print(A * B)
print(A * 10)
# Numpy数据可以生成N维数组
# 数学上将一维数组称为向量，二维数组称为矩阵
# 张量 tensor

# 广播
# 形状不同的数组之间也可以进行运算
C = np.array([[1, 2], [3, 4]])
D = np.array([10, 20])
C * D

# 访问元素
# 元素的索引从0开始
E = np.array([[51, 55], [14, 19], [0, 4]])
print('E')
print(E)
print(E[0])
print(E[0][1])
for row in E:
    print('row ：', row)
E = E.flatten()  # 将E转化为一维数组
print(E)
print(E[np.array([0, 2, 4])])  # 获取索引为0，2，4的元素
print(E > 15)  # [ True  True False  True False False]
print(E[E > 15])  # [51 55 19]


import os
import math
import csv
from scipy import stats
from itertools import combinations
import time

def ttest(writer, combo, a, b):
    sigFlag = 0
#    print("Combo of", combo[0], "and", combo[1])
    sumA = float(sum(a))
    sumB = float(sum(b))

    sumAsq = sumA ** 2
    sumBsq = sumB ** 2

    avgA = sumA/len(a)
    avgB = sumB/len(b)

    ssqA = sum(map(lambda x: x ** 2, a))
    ssqB = sum(map(lambda x: x ** 2, b))
    df = len(a) + len(b) - 2

    t = (avgA - avgB)/math.sqrt((((ssqA - sumAsq/len(a))+(ssqB - sumBsq/len(b)))/df)*(1.0/len(a)+1.0/len(b)))
#    print("T value ->", t)

    pval = stats.t.sf(abs(t), df)*2
#    print("2 Tailed P value ->", pval)

    if(pval < 0.05):
        sigFlag = 1
    res = [combo[0], combo[1], round(t, 5), df, round(pval, 6), sigFlag]
    writer.writerow(res)
#    print(res)

def main():
    ctr = 0
    path = os.getcwd()
    start = time.time()
    results = open(path + '\\results.csv', 'wt', newline='')
    writer = csv.writer(results, delimiter = ',')
    head = ['var_1', 'var_2', 't_value', 'degrees_of_freedom', 'p_value', 'significant']
    writer.writerow(head)
    rstart = time.time()
    csvFile = path + "\\data\\NMttest.csv"
    with open(csvFile, newline='') as fp:
        reader = csv.DictReader(fp)
        data = {}
        for row in reader:
            for header, value in row.items():
                try:
                    data[header].append(value)
                except KeyError:
                    data[header] = [value]
        for key, value in data.items():
            data[key] = list(filter(None, data[key]))
            data[key] = list(map(lambda x: float(x), data[key]))
        featureCombos = (list(combinations(data.keys(),2)))
        print("Time to read file ->", round(time.time() - rstart, 3), "seconds.", end = '\n')
        print("Total Combinations ->", len(featureCombos))
        for elem in featureCombos:
            ctr += 1
            sampleA = data[elem[0]]
            sampleB = data[elem[1]]
            ttest(writer, elem, sampleA, sampleB)
            print('Write success. Combination number ->', ctr, end = '\n')
#        print(data)
#    csvFile.close()
    results.close()
    fin = time.time() - start
    print("Total Time Elapsed ->", round(fin, 3), "seconds." ,end = '\n')
if __name__ == '__main__':
    main()


"""
2차원 Convolution(합성곱) 연산
"""
import numpy as np

def convolution_2d(x, w):
    """x, w: 2d ndarray. x의 shape이 w.shape와 같다.
        x와 w의 교차 상관 연산 결과를 return
    """
    xh, xw = x.shape[0], x.shape[1]

    # 2d 배열 w의 가로(width) ww,  세로(height) wh
    wh, ww = w.shape[0], w.shape[1]
    row_num = xh - wh + 1
    col_num = xw - ww + 1
    result = []
    for i in range(row_num):
        for j in range(col_num):
            x_sub = x[i:wh + i, j:ww + j]
            fma = np.sum(x_sub * w)
            result.append(fma)
    conv_ = np.array(result).reshape((row_num, col_num))
    return conv_

if __name__ == '__main__':
    np.random.seed(113)
    x = np.arange(1, 10).reshape((3, 3))
    print(x)
    w = np.array([[2, 0],
                  [0, 0]])
    print(w)

    # 2d 배열 x의 가로(width) xw 2,  세로(height) xh 2
    xh, xw = x.shape[0], x.shape[1]

    # 2d 배열 w의 가로(width) ww 2,  세로(height) wh 2
    wh, ww = w.shape[0], w.shape[1]

    x_sub1 = x[0:wh, 0:ww]
    print('x_sub1:', x_sub1)
    fma1 = np.sum(x_sub1 * w)
    print('fma1:', fma1)
    x_sub2 = x[0:wh, 1:1 + ww]
    print('x_sub2:', x_sub2)
    fma2 = np.sum(x_sub2 * w)
    print('fam2:', fma2)

    x_sub3 = x[1:1 + wh, 0:ww]
    print('x_sub3:', x_sub3)
    fma3 = np.sum(x_sub3 * w)
    print('fam3:', fma3)

    x_sub4 = x[1:1 + wh, 1:1 + ww]
    print('x_sub4:', x_sub4)
    fma4 = np.sum(x_sub4 * w)
    print('fam4:', fma4)

    conv = np.array([fma1, fma2, fma3, fma4]).reshape((2, 2))
    print('conv:', conv)

    x_result = convolution_2d(x, w)
    print(x_result)

    x = np.random.randint(10, size=(5, 5))
    w = np.random.randint(5, size=(3, 3))
    x_result = convolution_2d(x, w)
    print('x:', x)
    print('w:', w)
    print('result:', x_result)


import numpy as np
import warnings

#	returns the Mean Percentage Error between two Numpy Arrays. The two lists must be of the same size and greater than 0.
def mpe(prediction, actual):

	try:
		return np.mean((prediction - actual) / actual)
	except:
		return 'NA'

#	returns the Coefficient of Variation between two Numpy Arrays. The two lists must be of the same size and greater than 0.
def cv(prediction, actual):
	return rmse(prediction, actual)/np.mean(actual)

#   returns the Root-Mean-Square Error between two Numpy Arrays. The two lists must be of the same size and greater than 0.
def rmse(prediction, actual):
	return np.sqrt(((prediction - actual) ** 2).mean())

#   returns the Mean Absolute Percentage Error between two Numpy Arrays. The two lists must be of the same size and no values of 0 in Actual list.
def mape(prediction, actual):
	try:
		return np.mean(np.abs((actual - prediction) / actual))
	except:
		return 'NA'

def MAPE_pos(prediction,actual):
    eva = np.abs(actual) > (0.05 * np.abs(np.mean(actual)))
    return np.mean(np.abs((actual[eva] - prediction[eva]) / actual[eva]))

def cv_pos(prediction,actual):
    eva = np.abs(actual) > (0.05 * np.mean(np.abs(actual)))
    return np.sqrt(np.mean((prediction[eva]-actual[eva])**2))/np.mean(actual[eva])

def rmse_pos(prediction,actual):
    eva = np.abs(actual) > (0.05 * np.mean(np.abs(actual)))
    if sum(eva) == 0: # If the actual is always zero, then evaluate on the prediction
        eva = np.abs(prediction) > (0.05 * np.mean(np.abs(prediction)))
    return np.sqrt(np.mean((prediction[eva]-actual[eva])**2))

def mpe_pos(prediction,actual):
    eva = np.abs(actual) > (0.05 * np.abs(np.mean(actual)))
    return mpe(prediction[eva],actual[eva])

def getErrors(prediction, actual):

	mpe_err = mpe(prediction, actual)
	mape_err = mape(prediction,actual)
	cv_err = cv(prediction,actual)

	print("MPE is",mpe_err)
	print("MAPE is",mape_err)
	print("CV is",cv_err)
	# print("RMSE is",rmse_err)

	mpe_err = str(mpe_err)[0:10]
	mape_err = str(mape_err)[0:10]
	cv_err = str(cv_err)[0:10]

	# print(mpe_err, type(mpe_err))

	return [mpe_err,mape_err,cv_err]


import numpy as np
import matplotlib.pyplot as plt

mean = 1
stdev = 0.5

x = np.random.normal(loc=mean, scale=stdev,size=(10000))

plt.figure()
plt.title("Normal Distribution (mean= "+ str(mean)+ ", stdev= "+ str(stdev)+ ")")
plt.hist(x)

####################################################################################
n = 10
p = 0.5

y = np.random.binomial(n=n, p=p, size=1000)

plt.figure()
plt.title("Binomial Distribution (n= "+ str(n) + ", p= "+ str(p)+ ")")
plt.hist(y)


import numpy as np
import random
import math
from scipy.spatial.transform import Rotation as scipyR

# Math
def euclidean_dist(p1, p2):
    return math.sqrt(sum([(a - b)** 2 for a, b in zip(p1, p2)]))

def vec(p1, p2):
    """ vector from p1 to p2 """
    if type(p1) != np.ndarray:
        p1 = np.array(p1)
    if type(p2) != np.ndarray:
        p2 = np.array(p2)
    return p2 - p1

def proj(vec1, vec2, scalar=False):
    # Project vec1 onto vec2. Returns a vector in the direction of vec2.
    scale = np.dot(vec1, vec2) / np.linalg.norm(vec2)
    if scalar:
        return scale
    else:
        return vec2 * scale

def R_x(th):
    return np.array([
        1, 0, 0, 0,
        0, np.cos(th), -np.sin(th), 0,
        0, np.sin(th), np.cos(th), 0,
        0, 0, 0, 1
    ]).reshape(4,4)

def R_y(th):
    return np.array([
        np.cos(th), 0, np.sin(th), 0,
        0, 1, 0, 0,
        -np.sin(th), 0, np.cos(th), 0,
        0, 0, 0, 1
    ]).reshape(4,4)

def R_z(th):
    return np.array([
        np.cos(th), -np.sin(th), 0, 0,
        np.sin(th), np.cos(th), 0, 0,
        0, 0, 1, 0,
        0, 0, 0, 1
    ]).reshape(4,4)

def T(dx, dy, dz):
    return np.array([
        1, 0, 0, dx,
        0, 1, 0, dy,
        0, 0, 1, dz,
        0, 0, 0, 1
    ]).reshape(4,4)

def to_radians(th):
    return th*np.pi / 180

def to_degrees(th):
    return th*180 / np.pi

def R_between(v1, v2):
    if len(v1) != 3 or len(v2) != 3:
        raise ValueError("Only applicable to 3D vectors!")
    v = np.cross(v1, v2)
    c = np.dot(v1, v2)
    s = np.linalg.norm(v)
    I = np.identity(3)

    vX = np.array([
        0, -v[2], v[1],
        v[2], 0, -v[0],
        -v[1], v[0], 0
    ]).reshape(3,3)
    R = I + vX + np.matmul(vX,vX) * ((1-c)/(s**2))
    return R

def R_euler(thx, thy, thz, affine=False):
    """
    Obtain the rotation matrix of Rz(thx) * Ry(thy) * Rx(thz); euler angles
    """
    R = scipyR.from_euler("xyz", [thx, thy, thz], degrees=True)
    if affine:
        aR = np.zeros((4,4), dtype=float)
        aR[:3,:3] = R.as_dcm()
        aR[3,3] = 1
        R = aR
    return R

def R_quat(x, y, z, w, affine=False):
    R = scipyR.from_quat([x,y,z,w])
    if affine:
        aR = np.zeros((4,4), dtype=float)
        aR[:3,:3] = R.as_dcm()
        aR[3,3] = 1
        R = aR
    return R

def R_to_euler(R):
    """
    Obtain the thx,thy,thz angles that result in the rotation matrix Rz(thx) * Ry(thy) * Rx(thz)
    Reference: http://planning.cs.uiuc.edu/node103.html
    """
    return R.as_euler('xyz', degrees=True)
    # # To prevent numerical errors, avoid super small values.
    # epsilon = 1e-9
    # matrix[abs(matrix - 0.0) < epsilon] = 0.0
    # thz = to_degrees(math.atan2(matrix[1,0], matrix[0,0]))
    # thy = to_degrees(math.atan2(-matrix[2,0], math.sqrt(matrix[2,1]**2 + matrix[2,2]**2)))
    # thx = to_degrees(math.atan2(matrix[2,1], matrix[2,2]))
    # return thx, thy, thz

def R_to_quat(R):
    return R.as_quat()

def euler_to_quat(thx, thy, thz):
    return scipyR.from_euler("xyz", [thx, thy, thz], degrees=True).as_quat()

def quat_to_euler(x, y, z, w):
    return scipyR.from_quat([x,y,z,w]).as_euler("xyz", degrees=True)

def approx_equal(v1, v2, epsilon=1e-6):
    if len(v1) != len(v2):
        return False
    for i in range(len(v1)):
        if abs(v1[i] - v2[i]) > epsilon:
            return False
    return True


import numpy as np

# function that takes as input a list of numbers, and returns
# the list of values given by the softmax function.
def softmax(L):
    eL = np.exp(L)
    return np.divide(eL, eL.sum())

def cross_entropy(Y, P):
    Y = np.float_(Y)
    P = np.float_(P)
    return -np.sum(Y * np.log(P) + (1 - Y) * np.log(1 - P))


'''
Equivalence of AR(1) and MA(infinity)

To better understand the relationship between MA models and AR models, you will demonstrate that an AR(1) model is equivalent to an MA(∞
∞
) model with the appropriate parameters.

You will simulate an MA model with parameters 0.8,0.82,0.83,…
0.8
,
0.8
2
,
0.8
3
,
…
 for a large number (30) lags and show that it has the same Autocorrelation Function as an AR(1) model with ϕ=0.8
ϕ
=
0.8
.

INSTRUCTIONS
100XP
Import the modules for simulating data and plotting the ACF from statsmodels
Use a list comprehension to build a list with exponentially decaying MA parameters: 1,0.8,0.82,0.83,…
1
,
0.8
,
0.8
2
,
0.8
3
,
…
Simulate 5000 observations of the MA(30) model
Plot the ACF of the simulated series
'''

# import the modules for simulating data and plotting the ACF
from statsmodels.tsa.arima_process import ArmaProcess
from statsmodels.graphics.tsaplots import plot_acf

# Build a list MA parameters
ma = [0.8**i for i in range(30)]

# Simulate the MA(30) model
ar = np.array([1])
AR_object = ArmaProcess(ar, ma)
simulated_data = AR_object.generate_sample(nsample=5000)

# Plot the ACF
plot_acf(simulated_data, lags=30)
plt.show()


from matplotlib import pyplot as plt
import numpy as np
from skimage import io, color
from math import sqrt, exp

def distance(point1,point2):
    return sqrt((point1[0]-point2[0])**2 + (point1[1]-point2[1])**2)

def butterworthLP(lin, col, D0, n):
    base = np.zeros((lin,col))
    center = (lin/2,col/2)
    for x in range(lin):
        for y in range(col):
            base[y,x] = 1/(1+(distance((y,x),center)/D0)**(2*n))
    return base

def butterworthHP(lin, col, D0, n):
    base = butterworthLP(lin, col, D0, n)
    base = 1 - base
    return base

def gaussianLP(lin, col, D0):
    base = np.zeros((lin,col))
    center = (lin/2,col/2)
    for x in range(col):
        for y in range(lin):
            base[y,x] = exp(((-distance((y,x),center)**2)/(2*(D0**2))))
    return base

def gaussianHP(lin, col, D0):
    base = gaussianLP(lin, col, D0)
    base = 1 - base
    return base

im = io.imread('Lenna.png')

im2 = color.rgb2gray(im)
im2 = (im2 * 255).astype('uint8')

lin,col = im2.shape

#f1 = butterworthLP(51,51,7,2)
#f2 = butterworthHP(51,51,7,2)
#f3 = gaussianLP(51,51,7)
#f4 = gaussianHP(51,51,7)

f1 = butterworthLP(lin, col, 20, 2)
f2 = butterworthHP(lin, col, 120, 2)
f3 = gaussianLP(lin, col, 20)
f4 = gaussianHP(lin, col, 120)

plt.figure()
plt.subplot(221)
plt.imshow(f1)
plt.subplot(222)
plt.imshow(f2)
plt.subplot(223)
plt.imshow(f3)
plt.subplot(224)
plt.imshow(f4).

imft2 = np.fft.fft2(im2)
fshift2 = np.fft.fftshift(imft2)

blur1 = fshift2 * f1
bordas1 = fshift2 * f2
blur2 = fshift2 * f3
bordas2 = fshift2 * f4

blur1 = np.fft.ifft2(np.fft.ifftshift(blur1))
bordas1 = np.fft.ifft2(np.fft.ifftshift(bordas1))
blur2 = np.fft.ifft2(np.fft.ifftshift(blur2))
bordas2 = np.fft.ifft2(np.fft.ifftshift(bordas2))

plt.figure()
plt.subplot(221)
plt.imshow(np.abs(blur1), cmap='gray')
plt.subplot(222)
plt.imshow(np.abs(bordas1), cmap='gray')
plt.subplot(223)
plt.imshow(np.abs(blur2), cmap='gray')
plt.subplot(224)
plt.imshow(np.abs(bordas2), cmap='gray')


import numpy as np

""" Here I implemented the scoring functions.
    MAE, MSE, RMSE, RMSLE are included.

    Those are used for calculating differences between
    predicted values and actual values.

    Metrics are slightly differentiated. Sometimes squared, rooted,
    even log is used.

    Using log and roots can be perceived as tools for penalizing big
    errors. However, using appropriate metrics depends on the situations,
    and types of data
"""

# Mean Absolute Error
def mae(predict, actual):
    """
    Examples(rounded for precision):
    >>> actual = [1,2,3];predict = [1,4,3]
    >>> np.around(mae(predict,actual),decimals = 2)
    0.67

    >>> actual = [1,1,1];predict = [1,1,1]
    >>> mae(predict,actual)
    0.0
    """
    predict = np.array(predict)
    actual = np.array(actual)

    difference = abs(predict - actual)
    return difference.mean()

# Mean Squared Error
def mse(predict, actual):
    """
    Examples(rounded for precision):
    >>> actual = [1,2,3];predict = [1,4,3]
    >>> np.around(mse(predict,actual),decimals = 2)
    1.33

    >>> actual = [1,1,1];predict = [1,1,1]
    >>> mse(predict,actual)
    0.0
    """
    predict = np.array(predict)
    actual = np.array(actual)

    difference = predict - actual
    square_diff = np.square(difference)

    return square_diff.mean()

# Root Mean Squared Error
def rmse(predict, actual):
    """
    Examples(rounded for precision):
    >>> actual = [1,2,3];predict = [1,4,3]
    >>> np.around(rmse(predict,actual),decimals = 2)
    1.15

    >>> actual = [1,1,1];predict = [1,1,1]
    >>> rmse(predict,actual)
    0.0
    """
    predict = np.array(predict)
    actual = np.array(actual)

    difference = predict - actual
    square_diff = np.square(difference)
    mean_square_diff = square_diff.mean()
    return np.sqrt(mean_square_diff)

# Root Mean Square Logarithmic Error
def rmsle(predict, actual):
    """
    Examples(rounded for precision):
    >>> actual = [10,10,30];predict = [10,2,30]
    >>> np.around(rmsle(predict,actual),decimals = 2)
    0.75

    >>> actual = [1,1,1];predict = [1,1,1]
    >>> rmsle(predict,actual)
    0.0
    """
    predict = np.array(predict)
    actual = np.array(actual)

    log_predict = np.log(predict + 1)
    log_actual = np.log(actual + 1)

    difference = log_predict - log_actual
    square_diff = np.square(difference)
    mean_square_diff = square_diff.mean()

    return np.sqrt(mean_square_diff)

# Mean Bias Deviation
def mbd(predict, actual):
    """
    This value is Negative, if the model underpredicts,
    positive, if it overpredicts.

    Example(rounded for precision):

    Here the model overpredicts
    >>> actual = [1,2,3];predict = [2,3,4]
    >>> np.around(mbd(predict,actual),decimals = 2)
    50.0

    Here the model underpredicts
    >>> actual = [1,2,3];predict = [0,1,1]
    >>> np.around(mbd(predict,actual),decimals = 2)
    -66.67
    """
    predict = np.array(predict)
    actual = np.array(actual)

    difference = predict - actual
    numerator = np.sum(difference) / len(predict)
    denumerator = np.sum(actual) / len(predict)
    # print(numerator, denumerator)
    score = float(numerator) / denumerator * 100

    return score


import numpy as np
import matplotlib.pyplot as plt

'''
La siguiente función retorna el integrando de la función de Bessel J_m(x). Sus parámetros son m, x, y la variable de integración t.
'''
def bessel_integrand(m, x, t):
    return 1.0/np.pi * np.cos(m*t - x*np.sin(t))

'''
La siguiente función realiza la integral entre a y b de la función f para un número de pasos N utilizando la regla de Simpson. Los parámetros m y x son los correspondientes a J_m(x).
'''
def simpson(f, a, b, N, m, x):
    if N%2 == 1:
        N += 1
    h = (b-a)/N
    result = f(m,x,a) + f(m,x,b)
    for i in range(1, N, 2):
        result += 4*f(m,x,a + i*h)
    for i in range(2, N-1, 2):
        result += 2*f(m,x,a + i*h)
    result *= h/3.0
    return result

'''
Note que una integral corresponde a un punto de las gráficas que se quieren obtener. Entonces, la siguiente función realiza el procedimiento varias veces, generando arreglos para el eje X y el eje Y de las gráficas
'''
def plot_bessel(m):
    X = np.linspace(0,20,41)
    Y =np.zeros(41)
    for i in list(range(len(X))):
        Y[i]=simpson(bessel_integrand, 0.0, np.pi, 1000, m, X[i])

    plt.plot(X,Y)
    plt.xlabel("$x$", fontsize = "15")
    plt.ylabel("$J_m(x)$", fontsize = "15")
    plt.title("$m = $"+str(m), fontsize="15")
    plt.show()
    plt.close()

'''
Ahora sólo queda llamar esta función para cada m.
'''
plot_bessel(0)
plot_bessel(1)
plot_bessel(2)


import numpy
from matplotlib import pyplot

def trapezoidal(f, a, b, N):
    x, dx = numpy.linspace(a, b, N+1, retstep=True)
    fx = f(x)
    return dx * ( (fx[0] + fx[-1])/2 + numpy.sum(fx[1:-1]) )

def simpsons(f, a, b, N):
    x, dx = numpy.linspace(a, b, N+1, retstep=True)
    fx = f(x)
    return dx/3 * ( (fx[0] + fx[-1]) + \
        2*numpy.sum(fx[2:-1:2]) + 4*numpy.sum(fx[1:-1:2]) )

def richardson(f, a, b, N):
    I_h = simpsons(f, a, b, N)
    I_2h = simpsons(f, a, b, N//2)
    return (2**4*I_h - I_2h) / (2**4 - 1)

if __name__=="__main__":
    print("Trapezoidal rule")
    print(trapezoidal(numpy.sin, 0, numpy.pi/2, 2))
    print(trapezoidal(numpy.sin, 0, numpy.pi/2, 4))
    Npoints = 2**numpy.arange(1,20)
    dx_all = numpy.pi/2/Npoints
    errors = numpy.zeros_like(dx_all)
    for i, N in enumerate(Npoints):
        I = trapezoidal(numpy.sin, 0, numpy.pi/2, N)
        errors[i] = abs(I - 1)
    pyplot.loglog(dx_all, errors, 'kx')
    pyplot.loglog(dx_all, errors[0]*(dx_all/dx_all[0])**2, 'b-',
                  label=r"$\propto \Delta x^2$")
    pyplot.legend(loc='upper left')
    pyplot.xlabel(r"$\Delta x$")
    pyplot.ylabel("Error")
    pyplot.show()

    print("Simpson's rule")
    print(simpsons(numpy.sin, 0, numpy.pi/2, 2))
    print(simpsons(numpy.sin, 0, numpy.pi/2, 4))
    Npoints = 2**numpy.arange(1,20)
    dx_all = numpy.pi/2/Npoints
    errors = numpy.zeros_like(dx_all)
    for i, N in enumerate(Npoints):
        I = simpsons(numpy.sin, 0, numpy.pi/2, N)
        errors[i] = abs(I - 1)
    pyplot.loglog(dx_all, errors, 'kx')
    pyplot.loglog(dx_all, errors[0]*(dx_all/dx_all[0])**4, 'b-',
                  label=r"$\propto \Delta x^4$")
    pyplot.legend(loc='upper left')
    pyplot.xlabel(r"$\Delta x$")
    pyplot.ylabel("Error")
    pyplot.show()

    print("Richardson extrapolation")
    print(richardson(numpy.sin, 0, numpy.pi/2, 4))
    print(richardson(numpy.sin, 0, numpy.pi/2, 8))
    Npoints = 2**numpy.arange(2, 10)
    dx_all = numpy.pi/2/Npoints
    errors = numpy.zeros_like(dx_all)
    for i, N in enumerate(Npoints):
        I = richardson(numpy.sin, 0, numpy.pi/2, N)
        errors[i] = abs(I - 1)
    pyplot.loglog(dx_all, errors, 'kx')
    pyplot.loglog(dx_all, errors[0]*(dx_all/dx_all[0])**6, 'b-',
                  label=r"$\propto \Delta x^6$")
    pyplot.legend(loc='upper left')
    pyplot.xlabel(r"$\Delta x$")
    pyplot.ylabel("Error")
    pyplot.show()


import math
import numpy as np
from common.constant import *

def MinkowskiDistance(vector_1 : np.array, vector_2 : np.array, p = 2) -> float:
    """
    计算两点的闵可夫斯基距离 \n
    p = 1 时为曼哈顿距离 \n
    p = 2 时为欧式距离 \n
    p = ∞ 时为切比雪夫距离 \n
    """

    temp = np.abs(vector_1 - vector_2)
    return np.sum(temp ** p) ** (1 / p)

def Mahalanobis_distance(vector_1 : np.ndarray, vector_2 : np.ndarray, S_inv : np.ndarray) -> float:
    """
    计算两点的马哈拉诺比斯距离 \n
    :param S_inv: 协方差矩阵的逆矩阵 \n
    """
    temp_vector = vector_1 - vector_2
    temp_vector = temp_vector.reshape((-1, 1))

    dot_product = np.dot(temp_vector.T, np.dot(S_inv, temp_vector))
    if dot_product < 0:
        raise Exception('The number to calculate the square root is negative.')
    dis = math.sqrt(dot_product)
    return dis

def get_EuclideanDistance_matrix(X : np.ndarray, V : np.ndarray) -> np.ndarray:
    c = V.shape[MatrixShapeIndex.column]
    n = X.shape[MatrixShapeIndex.column]

    distance_matrix = np.zeros((n, c))

    for i in range(n):
        for j in range(c):
            distance_matrix[i][j] = MinkowskiDistance(X[:, i], V[:, j])

    return distance_matrix

if __name__ == '__main__':
    a = np.array([1, 2])
    b = np.array([4, 6])
    print(MinkowskiDistance(a, b, 1))


import numpy as np
import tensornetwork as tn

def schmidt_decomposition_numpy(bipartitepurestate_tensor):
    """ Calculate the Schmidt decomposition of the given discrete bipartite quantum system

    This is called by :func:`schmidt_decomposition`. This runs numpy.

    :param bipartitepurestate_tensor: tensor describing the bi-partitite states, with each elements the coefficients for :math:`|ij\\rangle`
    :return: list of tuples containing the Schmidt coefficient, eigenmode for first subsystem, and eigenmode for second subsystem
    :type bipartitepurestate_tensor: numpy.ndarray
    :rtype: list
    """
    state_dims = bipartitepurestate_tensor.shape
    mindim = np.min(state_dims)

    vecs1, diags, vecs2_h = np.linalg.svd(bipartitepurestate_tensor)
    vecs2 = vecs2_h.transpose()

    decomposition = [(diags[k], vecs1[:, k], vecs2[:, k])
                     for k in range(mindim)]

    decomposition = sorted(decomposition, key=lambda dec: dec[0], reverse=True)

    return decomposition

def schmidt_decomposition_tensornetwork(bipartitepurestate_tensor):
    """ Calculate the Schmidt decomposition of the given discrete bipartite quantum system

    This is called by :func:`schmidt_decomposition`. This runs tensornetwork.

    :param bipartitepurestate_tensor: tensor describing the bi-partitite states, with each elements the coefficients for :math:`|ij\\rangle`
    :return: list of tuples containing the Schmidt coefficient, eigenmode for first subsystem, and eigenmode for second subsystem
    :type bipartitepurestate_tensor: numpy.ndarray
    :rtype: list
    """
    state_dims = bipartitepurestate_tensor.shape
    mindim = np.min(state_dims)

    node = tn.Node(bipartitepurestate_tensor)
    vecs1, diags, vecs2_h, _ = tn.split_node_full_svd(node, [node[0]], [node[1]])

    decomposition = [(diags.tensor[k, k], vecs1.tensor[:, k], vecs2_h.tensor[k, :])
                     for k in range(mindim)]

    decomposition = sorted(decomposition, key=lambda dec: dec[0], reverse=True)

    return decomposition

def schmidt_decomposition(bipartitepurestate_tensor, approach='tensornetwork'):
    """Calculate the Schmidt decomposition of the given discrete bipartite quantum system

    Given a discrete normalized quantum system, given in terms of 2-D numpy array ``bipartitepurestate_tensor``,
    each element of ``bipartitepurestate_tensor[i, j]`` is the coefficient of the ket :math:`|ij\\rangle`,
    calculate its Schmidt decomposition, returned as a list of tuples, where each tuple contains
    the Schmidt coefficient, the vector of eigenmode of first subsystem, and the vector of the eigenmode of
    second subsystem.

    :param bipartitepurestate_tensor: tensor describing the bi-partitite states, with each elements the coefficients for :math:`|ij\\rangle`
    :param approach: using `numpy` or `tensornetwork` in computation. (default: `tensornetwork`)
    :return: list of tuples containing the Schmidt coefficient, eigenmode for first subsystem, and eigenmode for second subsystem
    :type bipartitepurestate_tensor: numpy.ndarray
    :type approach: str
    :rtype: list
    :raise: ValueError
    """
    if approach == 'numpy':
        return schmidt_decomposition_numpy(bipartitepurestate_tensor)
    elif approach == 'tensornetwork':
        return schmidt_decomposition_tensornetwork(bipartitepurestate_tensor)
    else:
        raise ValueError("Approach is either 'numpy' or 'tensorflow', not {}.".format(approach))


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

from pearsonLinearCorrelationCoefficient import pearson_linear_correlation_coefficient

def linear_regression(filename: str):
    df = pd.read_csv(filename, delimiter=',')
    number_of_rows = df.shape[0]
    df_hat = df.sum() / number_of_rows
    x_hat = df_hat[0]
    y_hat = df_hat[1]
    df['xi-x_hat'] = df.iloc[:, 0] - x_hat
    df['yi(xi-x_hat)'] = df['xi-x_hat'] * df.iloc[:, 1]
    df['(xi-x_hat)2'] = df['xi-x_hat'] ** 2
    df_sum = df.sum()
    a = df_sum['yi(xi-x_hat)'] / df_sum['(xi-x_hat)2']
    b = y_hat - x_hat * a
    return a, b

def draw_linear_regression(a: float, b: float, filename: str):
    df = pd.read_csv(filename, delimiter=',')
    column_names = df.columns
    df.plot(x=column_names[0], y=column_names[1], style='o', color='k')
    minX = df.iloc[:, 0].min()
    minX -= 0.1 * minX
    maxX = df.iloc[:, 0].max()
    maxX += 0.1 * maxX
    step = (maxX - minX) / 10
    regressionX = np.arange(minX, maxX, step)
    regressionY = a * regressionX + b
    plt.grid()
    plt.plot(regressionX, regressionY, 'r', linewidth=2)
    plt.xlabel(column_names[0])
    plt.ylabel(column_names[1])
    plt.legend(['y=f(x)', 'regression line'])
    fig = plt.gcf()
    fig.set_size_inches(5, 3.8)
    fig.tight_layout()
    plt.savefig('temp_regression_chart.png',  dpi=100)
    # plt.show()

print("Algorithm loaded: Linear regression")

"""
filename = '../data/pearsonLinearCorrelationCoefficient.csv'
r = pearson_linear_correlation_coefficient(filename)
print(f"Correlation coefficient: {r}")

if abs(r) < 0.5:
    print("Correlation coefficient should be less than |0.5|")
    exit(0)

a, b = linear_regression(filename)
print(f"a: {a}")
print(f"b: {b}")
draw_linear_regression(a, b, filename)
"""


"""
A number chain is created by continuously adding the square of the digits in a number to form a new number until it has been seen before.
For example,
44 > 32 > 13 > 10 > 1 > 1
85 > 89 > 145 > 42 > 20 > 4 > 16 > 37 > 58 > 89
Therefore any chain that arrives at 1 or 89 will become stuck in an endless loop. What is most amazing is that EVERY starting number will eventually arrive at 1 or 89.
How many starting numbers below ten million will arrive at 89?
"""

import numpy as np

def create_next(x):
	tmp_sum = 0
	while x > 0:
		tmp_sum += (x % 10)**2
		x /= 10
	return tmp_sum

def create_chain(x):
	chain = []
	next_num = x
	while 1:
		if next_num == 89:
			return True
		elif next_num == 1:
			return False
		elif next_num in chain:
			return False
		chain.append(next_num)
		next_num = create_next(next_num)

total_found = 0
for x in xrange(1,10000000):
	if x % 10000 == 0:
		print(x)
	if create_chain(x):
		total_found += 1

print("Found %d" % total_found) # 8581146


import numpy as np
from scipy.optimize import minimize

#ref for inequality constraint example syntax https://stackoverflow.com/questions/21765794/python-constrained-non-linear-optimization

'''
This is scipy kicking Google ORs a**.  Not only does it handle the linear version, it also
handles a nonlinear objective function with ease.  There must be a downside somewhere. Maybe not
as performant at scale? But so far so good...
'''

def objective(x):
    #linear objective
    return - ( np.dot(x, v) ) # x[1]*v[1] + ...x[n]*v[n]

    #non linear objective
    # return -( np.dot(x, v) + x[1]*v[1]*x[2]*v[2] )

def constraint1(x):
    return 20.0 -(np.dot(x, w)) # x[1]*w[1] + ...x[n]*w[n]

n = 3
x0 = np.array([1, 1, 5]) # initial guesses
w = np.array([1,4,1]) # weights
v = np.array([3,5,2]) # values

# show initial objective
print('Initial SSE Objective: ' + str(objective(x0)))

# optimize
bnds = ((1.0, 3.0), (1.0, 5.0), (10.0, 20.0))
con1 = {'type': 'ineq', 'fun': constraint1}
cons = ([con1])
solution = minimize(objective,x0,method='SLSQP',\
                    bounds=bnds,constraints=cons)
x = solution.x

# show final objective
print('Final SSE Objective: ' + str(round(objective(x))*(-1)))

#debug:check weight constraint is working. this number should be close to zero or going over weight
print('Overweight: ', str(20-(x[0]*w[0]+x[1]*w[1]+x[2]*w[2]) ))

# print solution
print('Solution')
print('x1 = ' + str(round(x[0])))
print('x2 = ' + str(round(x[1])))
print('x3 = ' + str(round(x[2])))


# coding: utf-8

# # Function iagaussian

# ## Synopse

# Generate a d-dimensional Gaussian image.
#
# - **g = gaussian(s, mu, cov)**
#
#   - **g**: Image.
#
#
#   - **s**: Image shape. (rows columns)
#   - **mu**: Image. Mean vector. n-D point. Point of maximum value.
#   - **cov**: Covariance matrix (symmetric and square).

# In[3]:

import numpy as np

def gaussian(s, mu, cov):
    d = len(s)  # dimension
    n = np.prod(s) # n. of samples (pixels)
    x = np.indices(s).reshape( (d, n))
    xc = x - mu
    k = 1. * xc * np.dot(np.linalg.inv(cov), xc)
    k = np.sum(k,axis=0) #the sum is only applied to the rows
    g = (1./((2 * np.pi)**(d/2.) * np.sqrt(np.linalg.det(cov)))) * np.exp(-1./2 * k)
    return g.reshape(s)

# ## Description

# A n-dimensional Gaussian image is an image with a Gaussian distribution. It can be used to generate
# test patterns or Gaussian filters both for spatial and frequency domain. The integral of the gaussian function is 1.0.

# ## Examples

# In[1]:

testing = (__name__ == "__main__")
if testing:
    get_ipython().system(' jupyter nbconvert --to python gaussian.ipynb')
    import numpy as np
    import sys,os
    ea979path = os.path.abspath('../../')
    if ea979path not in sys.path:
        sys.path.append(ea979path)
    import ea979.src as ia

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

# ### Example 1 - Numeric 2-dimensional

# In[2]:

if testing:
    f = ia.gaussian((8, 4), np.transpose([[3, 1]]), [[1, 0], [0, 1]])
    print('f=\n', np.array2string(f, precision=4, suppress_small=1))
    g = ia.normalize(f, [0, 255]).astype(np.uint8)
    print('g=\n', g)

# ## Example 2 - one dimensional signal

# In[3]:

# note that for 1-D case, the tuple has extra ,
# and the covariance matrix must be 2-D
if testing:
    f = ia.gaussian( (100,), 50, [[10*10]])
    g = ia.normalize(f, [0,1])
    plt.plot(g)
    plt.show()

# ### Example 3 - two-dimensional image

# In[4]:

if testing:
    f = ia.gaussian((150,250), np.transpose([[75,100]]), [[40*40,0],[0,30*30]])
    g = ia.normalize(f, [0,255]).astype(np.uint8)
    ia.adshow(g)

# ## Example 4 - Numeric 3-dimensional

# In[6]:

if testing:
    f = ia.gaussian((3,4,5), np.transpose([[1,2,3]]), [[1,0,0],[0,4,0],[0,0,9]])
    print('f=\n', np.array2string(f, precision=4, suppress_small=1))
    g = ia.normalize(f, [0,255]).astype(np.uint8)
    print('g=\n', g)

# ## Equation

# $$    f(x) = \frac{1}{\sqrt{2 \pi} \sigma} exp\left[ -\frac{1}{2} \left( \frac{x - \mu}{\sigma} \right)^2 \right]
# $$
#
# $$ f({\bf x}) = \frac{1}{(2 \pi)^{d/2}|\Sigma|^{1/2}} exp\left[ -\frac{1}{2}\left({\bf x} - \mu \right)^t\Sigma^{-1}\left({\bf x} - \mu \right)\right]
# $$


# -*- coding: utf-8 -*-
from math import *
from scipy.stats import norm
from scipy.optimize import fmin_bfgs

# Black Sholes Function
def price(S, K, T, r, v, callPutFlag = 'c'):
    d1 = (log(S / K) + (r + 0.5 * v**2) * T) / (v * sqrt(T))
    d2 = d1 - v * sqrt(T)
    if (callPutFlag == 'c') or (callPutFlag == 'C'):
        return S * norm.cdf(d1) - K * exp(-r * T) * norm.cdf(d2)
    else:
        return K * exp(-r * T) * norm.cdf(-d2) - S * norm.cdf(-d1)

# Calc Implied volatility
def implied_volatility(price_, S, K, T, r, callPutFlag = 'c'):
    Objective = lambda x: (price_ - price(S, K, T, r, x, callPutFlag))**2
    return fmin_bfgs(Objective, 1, disp=False)[0]

# test
if __name__ == '__main__':
    import time
    time_start = time.clock()
    # correct : call 3.68
    print(price(49.0, 50.0, 1.0, 0.01, 0.2, 'C'))
    time_elapsed = time.clock() - time_start
    print('time elapsed: %2f seconds' % time_elapsed)

    time_start = time.clock()
    # correct : put 4.18
    print(price(49.0, 50.0, 1.0, 0.01, 0.2, 'P'))
    time_elapsed = time.clock() - time_start
    print('time elapsed: %2f seconds' % time_elapsed)

    time_start = time.clock()
    # correct : 0.2
    print(implied_volatility(3.68, 49.0, 50.0, 1.0, 0.01, 'C'))
    time_elapsed = time.clock() - time_start
    print('time elapsed: %2f seconds' % time_elapsed)

    time_start = time.clock()
    # correct : 0.2
    print(implied_volatility(4.18, 49.0, 50.0, 1.0, 0.01, 'P'))
    time_elapsed = time.clock() - time_start
    print('time elapsed: %2f seconds' % time_elapsed)


import pandas as pd
import numpy as np

# Volatility literally refers to how "volatile" a stock is, meaning how unpredictably its price might change.
# A statistical measure of dispersion, such as standard deviation, is commonly used to measure volatility.

# In the exercise below, you're given daily prices for two sample stocks.
# Compute the standard deviations of their log returns, and return the ticker symbol for the stock that is more volatile.

def get_most_volatile(prices):
    """Return the ticker symbol for the most volatile stock.

    Parameters
    ----------
    prices : pandas.DataFrame
        a pandas.DataFrame object with columns: ['ticker', 'date', 'price']

    Returns
    -------
    ticker : string
        ticker symbol for the most volatile stock
    """
    # TODO: Fill in this function.
    curr_prices = prices.reset_index().pivot(index="date", columns="ticker", values="price")
    shifted_prices = curr_prices.shift(1)
    returns = curr_prices.applymap(np.log) - shifted_prices.applymap(np.log)
    std = returns.std()
    print(std)
    most_volatile = std.idxmax()
    print(most_volatile)
    # most_volatile = std.loc[most_volatile_value]
    # print(most_volatile)

    return most_volatile


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

import numpy as np

A = np.array([[1, 4, 6],
              [5, 2, 2],
              [-1, 6, 8]])

w, v = np.linalg.eig(A)
print(w)
print(v)

A = np.array([[1, 4, 6], [5, 2, 2], [-1, 6, 8]])
b = np.array([[1], [2], [3]])
x = np.linalg.solve(A, b)
print(x)


import numpy as np
import matplotlib.pyplot as plt
plt.style.use('fivethirtyeight')

# Snowflake time of flight

Have you ever watched a snowflake fall and thought, "How long has that snowflake been falling?"

Here, we want to determine the time of flight for a snowflake. We'll start simple and add some complexity to make a more accurate model.

## Simplest model

The simplest assumption we can make is that the only force acting on the snowflake is gravity. This leads to one differential equation,

$-mg = m\ddot{y}$

where $m$ is the mass of the snowflake, $g=9.81~\frac{m}{s^2}$, and $\ddot{y}$ is the second derivative with respect to time for the height of the snowflake i.e. its vertical acceleration.

We integrate this equation twice to create a solution in terms of $y_0$, initial height and $\dot{y}_0$, its initial vertical velocity.

$\ddot{y} = -g$

$\frac{d\dot{y}}{dt} = -g$

$\dot{y} -\dot{y}_0 = -gt$

$\frac{dy}{dt} = \dot{y}_0 -gt$

$y-y_0 = \dot{y}_0t - \frac{gt^2}{2}$

$y(t) = y_0 +\dot{y}_0t - \frac{gt^2}{2}$

Now, we need the initial height and initial speed of the snowflake. A typical cloud might sit $\approx 1,000~m$ above the ground and let's assume the initial vertical speed is 0 m/s.

This leaves, $y_0=1000~m~and~\dot{y}_0=0~m/s$

![Cloud heights and precipitation](https://upload.wikimedia.org/wikipedia/commons/5/57/Cloud_types_en.svg)

t = np.linspace(0, np.sqrt(1000/9.81*2), 1000)
y = 1000 - 9.81*t**2/2
plt.plot(t,y)
plt.xlabel('time (s)')
plt.ylabel('height (m)')

t[-1]

## Our solution - constant acceleration

According to your calculations, the snowflake will start at 1,000-m altitude and reach ground level at almost 14.3 seconds.

> __Note:__ What's wrong with the height curve here?

## A little problem - speed of snowflake

The graph of height-vs-time keeps getting steeper. The steeper the graph, the faster the snowflake. How fast is your snowflake traveling when it hits the ground?

dy = -9.81*t

plt.plot(t, dy)
plt.xlabel('time (s)')
plt.ylabel('vertical speed (m/s)')

According to your calculations, the snowflake is traveling at 140 m/s when it strikes the ground. This is >300 mph (or >500 km/h). Whoah...

If you caught this snowflake on your tongue it would feel like catching an icy [BB gun pellet](https://en.wikipedia.org/wiki/BB_gun#Safety), ouch!

You are missing a key force in the free body diagram that _slows_ down the snowflake, [_air resistance_ or drag](https://www.grc.nasa.gov/www/k-12/VirtualAero/BottleRocket/airplane/falling.html).

![Air drag free body diagram](https://www.grc.nasa.gov/www/k-12/VirtualAero/BottleRocket/airplane/Images/falling.gif)

## Improved model with air resistance

Adding drag to the free body diagram, now you have a new model.

$m\ddot{y} = -mg + C_d \frac{r\dot{y}^2}{2}A$

where $C_d$ is the [unitless drag coefficient](https://en.wikipedia.org/wiki/Drag_coefficient), $r=1.025~kg/m^3$ is the [density of air](https://www.macinstruments.com/blog/what-is-the-density-of-air-at-stp/),  $m=3~mg$ is the [mass of a snowflake](https://hypertextbook.com/facts/2001/JudyMoy.shtml), and $A=\piD^2/4$ is the area of the snowflake of [diameter](https://gpm.nasa.gov/sites/default/files/document_files/parsivel_Tokay_c3vp_agu.pdf) $D=6~mm$.

> __Note:__ The force of drag always opposes the velocity of the snowflake. Keep in mind if the snowflake moves upward, the force reverses direction.

Now, integrating  the equation can be a bit involved, but using v(t=0)=0, there results

$\frac{dv}{dt} = -g +\frac{C_d rA}{2}v^2$

$v(t) = -\sqrt{\frac{mg}{C_d rA}}\tanh\frac{g C_d rA}{m}t$

m = 3e-6 # mg
Cd = 0.5 # no units
r = 1.025 # kg/m/m/m
g = 9.81 #m/s/s
D = 6e-3 # mm - mm
A = np.pi*D**2/4
v = -np.sqrt(2*m*g/Cd/r/A)*np.tanh(g*Cd*r*A/m*t)
plt.plot(t, v)
plt.xlim(0,0.1)
plt.xlabel('time (s)')
plt.ylabel('vertical speed (m/s)')

### Make a comparison to previous model

In the constant acceleration model, the snowflake reached the ground in 14 seconds. In the improved air resistance model, you find that the snowflake only accelerates for 0.5 seconds. After that, it floats at a constant velocity until impact. This means, you can approximate that the snowflake travels at a constant velocity equal to its terminal velocity, $v_{term}$, as such

$\frac{dv}{dt} = 0 = -g +\frac{C_d rA}{2m}v_{term}^2$

$v_{term} = -\sqrt{\frac{2mg}{C_d rA}}$

vterm = np.sqrt(2*m*g/Cd/r/A)
t_improved = np.linspace(0,1000/vterm)
y_improved = 1000 - vterm*t_improved
plt.plot(t,y, label = 'constant acceleration')
plt.plot(t_improved,y_improved, label='constant velocity')
print('total flight time is {}'.format(t_improved[-1]))
plt.xlabel('time (s)')
plt.ylabel('height (m)')

## Wrapping up

The first model you created assumed constant acceleration, but after accounting for drag you found out that a snowflake reaches a terminal velocity in less than 0.5 seconds. The more accurate model to calculate time of flight was actually a constant velocity model.

You found that the snowflake drifts slowly to the surface over the course of 496 seconds (or 8 minutes). Gently landing at 2 m/s.


###
# Introduction to Data Science Homework Assignment # 1
# Student: Alan Fernandez, aefernandez@wpi.edu
# Date: 08/29/18
# Course: DS501, Introduction to Data Science (Grad Level)
# Worcester Polytechnic Institute (WPI), Worcester, MA
###

import numpy as np

from problem3 import random_walk

#-------------------------------------------------------------------------
'''
    Problem 4: Solving sink-node problem in PageRank
    In this problem, we implement the pagerank algorithm which can solve the sink node problem.
    You could test the correctness of your code by typing `nosetests test4.py` in the terminal.
'''

#--------------------------
def compute_S(A):
    '''
        compute the transition matrix S from addjacency matrix A, which solves sink node problem by filling the all-zero columns in A.
        S[j][i] represents the probability of moving from node i to node j.
        If node i is a sink node, S[j][i] = 1/n.
        Input:
                A: adjacency matrix, a (n by n) numpy matrix of binary values. If there is a link from node i to node j, A[j][i] =1. Otherwise A[j][i]=0 if there is no link.
        Output:
                S: transition matrix, a (n by n) numpy matrix of float values.  S[j][i] represents the probability of moving from node i to node j.
    The values in each column of matrix S should sum to 1.
    '''
#########################################
## INSERT YOUR CODE HERE
    #print(A)
    # sum of each column of A
    column_sum = A.sum(axis = 0)

    # create a diagonal matrix
    sum_vector = column_sum.getA1()
    D = np.diag(np.where(sum_vector == 0, 1, sum_vector))
    #print(D)
    # normalize each column of A

    # Invert the diagonal matrix to divide the adjacency matrix by the sum of the columns.
    D = np.linalg.inv(D)

    # Multiply the matrices to execute the division. This returns the transition matrix.
    S = A * D

    # Determine the number of elements in each column
    n = S.shape[0]

    # Iterate through each column, determine if its a sink node, and replace with all equal probabilities.
    for index, column in enumerate(S):
        if ~S[:,index].any(axis=0).any():
            S[:,index] = 1/n

    return S
#########################################

#--------------------------
def pagerank_v2(A):
    '''
        A simplified version of PageRank algorithm, which solves the sink node problem.
        Given an adjacency matrix A, compute the pagerank score of all the nodes in the network.
        Input:
                A: adjacency matrix, a numpy matrix of binary values. If there is a link from node i to node j, A[j][i] =1. Otherwise A[j][i]=0 if there is no link.
        Output:
                x: the ranking scores, a numpy vector of float values, such as np.array([[.3], [.5], [.7]])
    '''

    # Initialize the score vector with all one values
    num_nodes, _ = A.shape
    x_0 =  np.asmatrix(np.ones((num_nodes,1)))

    # compute the transition matrix from adjacency matrix
    S = compute_S(A)
    # random walk
    x, n_steps = random_walk(S,x_0)

    return x


# -*- coding: utf-8 -*-
"""
Created on Sat Apr 11 19:55:21 2020

@author: nmazzilli24
"""

import numpy as np
import math

'''
1 - Building basic functions with numpy
Numpy is the main package for scientific computing in Python. It is maintained by a large community (www.numpy.org). In this exercise you will learn several key numpy functions such as np.exp, np.log, and np.reshape. You will need to know how to use these functions for future assignments.

1.1 - sigmoid function, np.exp()
Before using np.exp(), you will use math.exp() to implement the sigmoid function. You will then see why np.exp() is preferable to math.exp().

Exercise: Build a function that returns the sigmoid of a real number x. Use math.exp(x) for the exponential function.

Reminder:  sigmoid(x)=11+e−xsigmoid(x)=11+e−x  is sometimes also known as the logistic function. It is a non-linear function used not only in Machine Learning (Logistic Regression), but also in Deep Learning.
'''

def basic_sigmoid(x):
    """
    Compute sigmoid of x.

    Arguments:
    x -- A scalar

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

    ### START CODE HERE ### (≈ 1 line of code)
    s = 1/(1+math.exp(-x))
    ### END CODE HERE ###

    return s

'''
Any time you need more info on a numpy function, we encourage you to look at the official documentation.

You can also create a new cell in the notebook and write np.exp? (for example) to get quick access to the documentation.

Exercise: Implement the sigmoid function using numpy.

Instructions: x could now be either a real number, a vector, or a matrix. The data structures we use in numpy to represent these shapes (vectors, matrices...) are called numpy arrays. You don't need to know more for now.

'''

def sigmoid(x):
    """
    Compute the sigmoid of x

    Arguments:
    x -- A scalar or numpy array of any size

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

    ### START CODE HERE ### (≈ 1 line of code)
    s = 1/(1+np.exp(-x))
    ### END CODE HERE ###

    return s

'''
1.2 - Sigmoid gradient
As you've seen in lecture, you will need to compute gradients to optimize loss functions using backpropagation. Let's code your first gradient function.

Exercise: Implement the function sigmoid_grad() to compute the gradient of the sigmoid function with respect to its input x. The formula is:
sigmoid_derivative(x)=σ′(x)=σ(x)(1−σ(x))(2)
(2)sigmoid_derivative(x)=σ′(x)=σ(x)(1−σ(x))

You often code this function in two steps:

Set s to be the sigmoid of x. You might find your sigmoid(x) function useful.
Compute  σ′(x)=s(1−s)σ′(x)=s(1−s)
'''

def sigmoid_derivative(x):
    """
    Compute the gradient (also called the slope or derivative) of the sigmoid function with respect to its input x.
    You can store the output of the sigmoid function into variables and then use it to calculate the gradient.

    Arguments:
    x -- A scalar or numpy array

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

    ### START CODE HERE ### (≈ 2 lines of code)
    s = sigmoid(x)
    ds = s*(1-s)
    ### END CODE HERE ###

    return ds
'''
1.3 - Reshaping arrays
Two common numpy functions used in deep learning are np.shape and np.reshape().

X.shape is used to get the shape (dimension) of a matrix/vector X.
X.reshape(...) is used to reshape X into some other dimension.
For example, in computer science, an image is represented by a 3D array of shape  (length,height,depth=3)(length,height,depth=3) . However, when you read an image as the input of an algorithm you convert it to a vector of shape  (length∗height∗3,1)(length∗height∗3,1) . In other words, you "unroll", or reshape, the 3D array into a 1D vector.

Exercise: Implement image2vector() that takes an input of shape (length, height, 3) and returns a vector of shape (length*height*3, 1). For example, if you would like to reshape an array v of shape (a, b, c) into a vector of shape (a*b,c) you would do:

v = v.reshape((v.shape[0]*v.shape[1], v.shape[2])) # v.shape[0] = a ; v.shape[1] = b ; v.shape[2] = c
Please don't hardcode the dimensions of image as a constant. Instead look up the quantities you need with image.shape[0], etc.

'''

def image2vector(image):
    """
    Argument:
    image -- a numpy array of shape (length, height, depth)

    Returns:
    v -- a vector of shape (length*height*depth, 1)
    """

    ### START CODE HERE ### (≈ 1 line of code)
    v = image.reshape(image.shape[0]*image.shape[1]*image.shape[2],1)
    ### END CODE HERE ###

    return v

'''
1.4 - Normalizing rows
Another common technique we use in Machine Learning and Deep Learning is to normalize our data. It often leads to a better performance because gradient descent converges faster after normalization. Here, by normalization we mean changing x to  x∥x∥x∥x∥  (dividing each row vector of x by its norm).

For example, if
x=[023644](3)
(3)x=[034264]

then
∥x∥=np.linalg.norm(x,axis=1,keepdims=True)=[556⎯⎯⎯⎯√](4)
(4)∥x∥=np.linalg.norm(x,axis=1,keepdims=True)=[556]

and
x_normalized=x∥x∥=0256√35656√45456√(5)
(5)x_normalized=x∥x∥=[03545256656456]

Note that you can divide matrices of different sizes and it works fine: this is called broadcasting and you're going to learn about it in part 5.

Exercise: Implement normalizeRows() to normalize the rows of a matrix. After applying this function to an input matrix x, each row of x should be a vector of unit length (meaning length 1).

'''

def normalizeRows(x):
    """
    Implement a function that normalizes each row of the matrix x (to have unit length).

    Argument:
    x -- A numpy matrix of shape (n, m)

    Returns:
    x -- The normalized (by row) numpy matrix. You are allowed to modify x.
    """

    ### START CODE HERE ### (≈ 2 lines of code)
    # Compute x_norm as the norm 2 of x. Use np.linalg.norm(..., ord = 2, axis = ..., keepdims = True)
    x_norm = np.linalg.norm(x,axis =1, keepdims = True)

    # Divide x by its norm.
    x = x/x_norm
    ### END CODE HERE ###

    return x

'''
1.5 - Broadcasting and the softmax function¶
A very important concept to understand in numpy is "broadcasting". It is very useful for performing mathematical operations between arrays of different shapes. For the full details on broadcasting, you can read the official broadcasting documentation.

Exercise: Implement a softmax function using numpy. You can think of softmax as a normalizing function used when your algorithm needs to classify two or more classes. You will learn more about softmax in the second course of this specialization.

'''

def softmax(x):
    """Calculates the softmax for each row of the input x.

    Your code should work for a row vector and also for matrices of shape (m,n).

    Argument:
    x -- A numpy matrix of shape (m,n)

    Returns:
    s -- A numpy matrix equal to the softmax of x, of shape (m,n)
    """

    ### START CODE HERE ### (≈ 3 lines of code)
    # Apply exp() element-wise to x. Use np.exp(...).
    x_exp = np.exp(x)

    # Create a vector x_sum that sums each row of x_exp. Use np.sum(..., axis = 1, keepdims = True).
    x_sum = np.sum(x_exp,axis =1, keepdims = True)

    # Compute softmax(x) by dividing x_exp by x_sum. It should automatically use numpy broadcasting.
    s = x_exp/x_sum

    ### END CODE HERE ###

    return s

'''
2.1 Implement the L1 and L2 loss functions
Exercise: Implement the numpy vectorized version of the L1 loss. You may find the function abs(x) (absolute value of x) useful.

Reminder:

The loss is used to evaluate the performance of your model. The bigger your loss is, the more different your predictions (ŷ y^) are from the true values (yy). In deep learning, you use optimization algorithms like Gradient Descent to train your model and to minimize the cost.
L1 loss is defined as:

'''

def L1(yhat, y):
    """
    Arguments:
    yhat -- vector of size m (predicted labels)
    y -- vector of size m (true labels)

    Returns:
    loss -- the value of the L1 loss function defined above
    """

    ### START CODE HERE ### (≈ 1 line of code)
    loss = np.sum(abs(y-yhat))
    ### END CODE HERE ###

    return loss

#Testing functions
def main():
    print("Testing basic_sigmoid function")
    test_sig = basic_sigmoid(3)
    sig_sol = 0.952
    tol = 0.001
    assert(abs(test_sig-sig_sol) < tol)
    print("Passed the basic_sigmoid function!")
    print()

    #Testing the sigmoid with np apis
    print("Testing sigmoid function")
    x = np.array([1, 2, 3])
    test_sig_np = sigmoid(x)
    sig_np_sol = [ 0.73105858, 0.88079708, 0.95257413]

    #https://docs.scipy.org/doc/numpy/reference/generated/numpy.allclose.html
    assert(np.allclose(test_sig_np,sig_np_sol, tol))
    print("Passed the basic_sigmoid function!")
    print()

    #Sigmoid Derivative Test
    print("Testing sigmoid_derivative function")
    x = np.array([1, 2, 3])
    test_sig_deriv = sigmoid_derivative(x)
    test_sig_deriv_sol = [ 0.19661193, 0.10499359, 0.04517666]
    assert(np.allclose(test_sig_deriv,test_sig_deriv_sol, tol))
    print("Passed the sigmoid_derivative function!")
    print()

    #Normalize Row Test
    print("Testing normalizeRows function")
    x = np.array([
    [0, 3, 4],
    [1, 6, 4]])
    norm_row = normalizeRows(x)
    norm_row_sol = [[ 0., 0.6, 0.8 ], [ 0.13736056, 0.82416338, 0.54944226]]
    assert(np.allclose(norm_row,norm_row_sol, tol))
    print("Passed the normalizeRows function!")
    print()

    #Testing Softmax Funciton
    print("Testing softmax function")
    x = np.array([
    [9, 2, 5, 0, 0],
    [7, 5, 0, 0 ,0]])
    softmax_res = softmax(x)
    softmax_sol = [[ 9.80897665e-01, 8.94462891e-04, 1.79657674e-02, 1.21052389e-04, 1.21052389e-04], [ 8.78679856e-01, 1.18916387e-01, 8.01252314e-04, 8.01252314e-04, 8.01252314e-04]]
    np.testing.assert_allclose(softmax_res,softmax_sol,rtol=1e-5, atol=0)
    print("Passed the softmax function!")
    print()

    #Testing L1 Function
    print("Testing L1 function")
    yhat = np.array([.9, 0.2, 0.1, .4, .9])
    y = np.array([1, 0, 0, 1, 1])
    L1_test = L1(yhat,y)
    L1_sol = 1.1
    assert(abs(L1_test-L1_sol) < tol)
    print("Passed the L1 function!")
    print()

    ''' Framework for Computational Time
    import time

    x1 = [9, 2, 5, 0, 0, 7, 5, 0, 0, 0, 9, 2, 5, 0, 0]
    x2 = [9, 2, 2, 9, 0, 9, 2, 5, 0, 0, 9, 2, 5, 0, 0]

    ### CLASSIC DOT PRODUCT OF VECTORS IMPLEMENTATION ###
    tic = time.process_time()
    dot = 0
    for i in range(len(x1)):
        dot+= x1[i]*x2[i]
    toc = time.process_time()
    print ("dot = " + str(dot) + "\n ----- Computation time = " + str(1000*(toc - tic)) + "ms")

    ### CLASSIC OUTER PRODUCT IMPLEMENTATION ###
    tic = time.process_time()
    outer = np.zeros((len(x1),len(x2))) # we create a len(x1)*len(x2) matrix with only zeros
    for i in range(len(x1)):
        for j in range(len(x2)):
            outer[i,j] = x1[i]*x2[j]
    toc = time.process_time()
    print ("outer = " + str(outer) + "\n ----- Computation time = " + str(1000*(toc - tic)) + "ms")

    ### CLASSIC ELEMENTWISE IMPLEMENTATION ###
    tic = time.process_time()
    mul = np.zeros(len(x1))
    for i in range(len(x1)):
        mul[i] = x1[i]*x2[i]
    toc = time.process_time()
    print ("elementwise multiplication = " + str(mul) + "\n ----- Computation time = " + str(1000*(toc - tic)) + "ms")

    ### CLASSIC GENERAL DOT PRODUCT IMPLEMENTATION ###
    W = np.random.rand(3,len(x1)) # Random 3*len(x1) numpy array
    tic = time.process_time()
    gdot = np.zeros(W.shape[0])
    for i in range(W.shape[0]):
        for j in range(len(x1)):
            gdot[i] += W[i,j]*x1[j]
    toc = time.process_time()
    print ("gdot = " + str(gdot) + "\n ----- Computation time = " + str(1000*(toc - tic)) + "ms")
'''

if __name__ == '__main__':
    main()


"""
This code implements a perceptron algorithm (PLA).
This is the version of the file that runs in Python 3.6:
- it does not plot
- it had to be adjusted to pandas 0.23.0 because Vocareum uses python 3.6

First, we visualise the dataset which contains 2 features. We can see that the dataset can be clearly separated by drawing a straight line between them. The goal is to write an algorithm that finds that line and classifies all of these data points correctly.

The output file (e.g. 'output1_f.csv') contains the values of w1, w2 and b which define the 'threshold' line. The last row will be the most accurate one. Each time it goes through each of the examples in 'input1.csv', it adds a new line to the output file containing a comma-separated list of the weights w_1, w_2, and b (bias) in that order.

Upon convergence, the program stops, and the final values of w_1, w_2, and b are printed to the output file (output1.csv). This defines the decision boundary that your PLA has computed for the given dataset.

Note: When implementing your PLA, in case of tie (sum of w_jx_ij = 0), please follow the lecture note and classify the datapoint as -1.

Ensure this file can be executed as:
$ python3 problem1.py input1.csv output1.csv

The code includes plotting functions. However those are disabled when executing the code from the command line in the format specified immediately above.

"""

# builtin modules
import os
import psutil
import requests
import sys

# 3rd party modules
import pandas as pd
import numpy as np
#import plotly.graph_objects as go

def get_data(source_file):

    # Define input and output filepaths
    input_path = os.path.join(os.getcwd(), source_file)

    # Read input data
    df = pd.read_csv(input_path)

    return df

def perceptron_classify(df, n:int = 200):
    """
    1. set b = w = 0
    2. for N iterations, or until weights do not change
        (a) for each training example xᵏ with label yᵏ
            i. if yᵏ — f(xᵏ) = 0, continue
            ii. else, update wᵢ, △wᵢ = (yᵏ — f(xᵏ)) xᵢ
    """

    # transform the dataframe to an array
    data = np.asmatrix(df, dtype = 'float64')

    # get the first two columns as pairs of values
    features = data[:, :-1]
    # get the last column
    labels = data[:, -1]

    # assign zero weight as a starting point to features and labels
    w = np.zeros(shape=(1, features.shape[1]+1)) #e.g. array([0., 0., 0.])
    w_ = np.empty(shape=[0,3]) # declare w_ as an empty matrix of same shape as w

    for iteration in range(0,n):
        for x, label in zip(features, labels):
            x = np.insert(x, 0, 1) # add a column of 1s to represent w0
            f = np.dot(w, x.transpose()) # a scalar
            #print(f)
            if f * label <= 0:
                w += (x * label.item(0,0)).tolist() # because label comes from being a matrix (matrix([[1.]])) and needs to be converted to scalar
            else:
                iteration = n

        w_ = np.vstack((w_, w))

    return w_

def write_csv(filename, weights):
    # write the outputs csv file
    filepath = os.path.join(os.getcwd(), filename)
    dataframe = pd.DataFrame(data=weights, columns=('b','w1','w2'))
    # reorder the columns in the dataframe in accordance with assignment
    order = [1,2,0] # setting column's order, 'b' goes as first column followed by weights
    dataframe = dataframe[[dataframe.columns[i] for i in order]]
    dataframe.to_csv(filepath, index = False, header = False)
    return print("New Outputs file saved to: <<", filename, ">>", sep='', end='\n')

def main():

    #take string of input data csv file
    in_data = str(sys.argv[1])

    #take string of input data csv file
    out_data = str(sys.argv[2])

    if in_data and out_data:
        #add functions execute here
        df = get_data(in_data)
        w_ = perceptron_classify(df)
        if w_.size:
            write_csv(out_data, w_)
            print("Plot and output csv files are ready !")
    else:
        print("Enter valid command arguments !")

if __name__ == '__main__':
    main()


import matplotlib.pyplot as plt
import numpy as np
import os
os.chdir('C:/Users/DELL/Desktop/Quant_macro')
import useful_functions as uf

f = lambda x: (x + np.abs(x))/2
x_bar = 2
start = 0
end_ = 6
num_g = 100

Tay1 = lambda x: uf.Taylor_any_f(x, x_bar, 1, f)
Tay2 = lambda x: uf.Taylor_any_f(x, x_bar, 2, f)
Tay5 = lambda x: uf.Taylor_any_f(x, x_bar, 5, f)
Tay20 = lambda x: uf.Taylor_any_f(x, x_bar, 20, f)

x_eval = np.linspace(start, end_, num_g)
x_eval = x_eval[1:-1]

Rg = [f(x_eval[i]) for i in range(len(x_eval))]
Tay20_o = [Tay20(x_eval[i]) for i in range(len(x_eval))]
Tay5_o = [Tay5(x_eval[i]) for i in range(len(x_eval))]
Tay2_o = [Tay2(x_eval[i]) for i in range(len(x_eval))]
Tay1_o = [Tay1(x_eval[i]) for i in range(len(x_eval))]

f, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2,2)
f.set_figheight(10)
f.set_figwidth(10)
ax1.plot(x_eval, Tay1_o, color = 'r', label = 'Taylor 1')
ax1.legend(loc='upper left')
ax1.set_xlabel('x')
ax1.set_ylabel('f(x)')
ax1.set_title('Expansion of Order 1')
ax2.plot(x_eval, Tay2_o, color = 'b', label = 'Taylor 2')
ax2.legend(loc='upper left')
ax2.set_xlabel('x')
ax2.set_ylabel('f(x)')
ax2.set_title('Expansion of Order 2')
ax3.plot(x_eval, Tay5_o, color = 'g', label = 'Taylor 5')
ax3.legend(loc='upper left')
ax3.set_xlabel('x')
ax3.set_ylabel('f(x)')
ax3.set_title('Expansion of Order 5')
ax4.plot(x_eval, Tay20_o, color = 'k', label = 'Taylor 20')
ax4.legend(loc='upper left')
ax4.set_xlabel('x')
ax4.set_ylabel('f(x)')
ax4.set_title('Expansion of Order 20')

f1, ax5 = plt.subplots(1,1)
f1.set_figheight(5)
f1.set_figwidth(10)
ax5.set_yscale('linear')
ax5.plot(x_eval, Tay1_o, color = 'r', label = 'Taylor 1')
ax5.plot(x_eval, Tay2_o, color = 'b', label = 'Taylor 2')
ax5.plot(x_eval, Tay5_o, color = 'g', label = 'Taylor 5')
ax5.plot(x_eval, Tay20_o, color = 'k', label = 'Taylor 20')
ax5.plot(x_eval, Rg, color = 'gold', label = 'True function')

ax5.legend(loc='upper left')
ax5.set_xlabel('x')
ax5.set_ylabel('f(x)')
ax5.set_title('The Taylor Expansions')


#!/usr/bin/env python3
import numpy as np
from numpy.linalg import inv
from scipy.spatial import distance
from math import sin
from math import cos
from numba import jit

@jit(forceobj=True)
def vector_angle(u,v):
    num = np.arccos( np.dot(u ,v) )
    den = np.power(np.dot(v,v),1/2) * np.power(np.dot(u,u),1/2 )
    angle = num / den
    if np.isnan(angle).any(0) == True:
        angle = 0
    return angle

@jit(forceobj=True)
def Rz(theta_z):
    a = theta_z
    T = np.array([[cos(a),-sin(a), 0,0 ],[sin(a),cos(a),0,0],[0,0,1,0],[0,0,0,1]],dtype = np.float32)
    return T

@jit(forceobj=True)
def Ry(theta_y):
    a = theta_y
    T =  np.array([[cos(a),0, sin(a),0 ],[0,1,0,0],[-sin(a),0,cos(a),0],[0,0,0,1]],dtype = np.float32)
    return T

@jit(forceobj=True)
def Rx(theta_x):
    a = theta_x
    T =  np.array([[1,0, 0,0 ],[0,cos(a),-sin(a),0],[0,sin(a),cos(a),0],[0,0,0,1]],dtype = np.float32)
    return T

@jit(forceobj=True)
def T_tr(dx,dy,dz):
    T =  np.array([[1 ,0 ,0 ,dx],[0,1,0,dy],[0,0,1,dz],[0,0,0,1]],dtype = np.float32)
    return T

@jit(forceobj=True)
def Tx(theta_x,dx,dy,dz):
    a = theta_x
    T =  np.array([[1,0, 0,dx ],[0,cos(a),-sin(a),dy],[0,sin(a),cos(a),dz],[0,0,0,1]],dtype = np.float32)
    return T

@jit(forceobj=True)
def Ty(theta_y,dx,dy,dz):
    a = theta_y
    T =  np.array([[cos(a),0, sin(a),dx ],[0,1,0,dy],[-sin(a),0,cos(a),dz],[0,0,0,1]],dtype = np.float32)
    return T

@jit(forceobj=True)
def Tz(theta_z,dx,dy,dz):
    a = theta_z
    T = np.array(   [   [cos(a),     -sin(a),    0,     dx],
                        [sin(a),      cos(a),    0,     dy],
                        [0     ,           0,    1,     dz],
                        [0     ,           0,    0,     1 ]
                        ] ,
                        dtype = np.float32 )
    return T

@jit
def solve_rr(x,y,L12,L23,elbow):
    num = np.power( L12, 2 ) + np.power( L23 , 2 ) - np.power( x , 2 ) - np.power( y , 2 )
    den = 2 * L12 * L23
    arg = num / den
    if elbow == "down":
        q2 = np.pi - np.arccos(arg)
    elif elbow == "up" :
        q2 = - np.arccos(- arg)
    else:
        print("wrong format,insert 1:up,or 2:down")
    q1 = np.arctan2(y,x) - np.arctan2((L23 * np.sin(q2)) , (L12 + L23 * np.cos(q2)))

    return q1,q2

@jit(forceobj=True)
def euler_angles(R):
    phi = np.arctan2(R[1,2] , R[0,2])
    theta = np.arctan2( np.power(np.power(R[0,2], 2) + np.power(R[1,2] ,2) ,1/2), R[2,2] )
    psi = np.arctan2( - R[2,1], R[2,1] )
    angles = np.asarray( [phi, theta, psi] )
    return angles

@jit(forceobj=True)
def mdot(*args):
    T = np.eye( args[0].shape[0] )
    for arg in args:
        T = np.dot( T , arg )
    return T

def T_DH(d_n,theta_n,r_n,alpha_n):
    ctheta = np.cos( theta_n )
    calpha = np.cos( alpha_n )
    stheta = np.sin( theta_n )
    salpha = np.sin( alpha_n )

    T = np.asarray  ( [ [ctheta ,   -stheta*calpha  , stheta*salpha     , r_n * ctheta  ] ,
                        [stheta ,   ctheta*calpha   , -ctheta*salpha    , r_n*stheta    ] ,
                        [0      ,   salpha          , calpha            , d_n           ] ,
                        [0      ,   0               , 0                 ,1              ] ]
                    )

    return T

import numpy,from numpy,from scipy,from numba


import numpy as np

def skew(a):
    """Returns skew symmetric matrix, given a 3-vector"""
    return np.array([
        [    0, -a[2],  a[1]],
        [ a[2],     0, -a[0]],
        [-a[1],  a[0],     0]
        ])

def rot1(t):
    return np.array([
        [1, 0, 0],
        [0, np.cos(t), -np.sin(t)],
        [0, np.sin(t),  np.cos(t)]
        ])

def rot2(t):
    return np.array([
        [np.cos(t), 0, np.sin(t)],
        [0, 1, 0],
        [-np.sin(t), 0, np.cos(t)]
        ])

def rot3(t):
    return np.array([
        [np.cos(t), -np.sin(t), 0],
        [np.sin(t), np.cos(t), 0],
        [0, 0, 1]
        ])

def rot2D(t):
    return np.array([
        [np.cos(t), -np.sin(t)],
        [np.sin(t),  np.cos(t)]
        ])

def euler2rot(phi, theta, psi):
    return rot3(psi) @ rot2(theta) @ rot1(phi)

def rot2euler(R):
    """Compute Euler angles from rotation matrix.
    yaw, pitch, roll: 3, 2, 1 rot sequence
    Note frame relationship: e^b = e^v R^{vb}
    """
    psi = np.arctan2(R[1, 0], R[0, 0]) # yaw angle
    theta = np.arcsin(-R[2, 0])        # pitch angle
    phi = np.arctan2(R[2, 1], R[2, 2]) # roll angle
    return (phi, theta, psi)

def conj(q):
    return np.concatenate([[q[0]], -q[1:]])

def prod(p, q):
    """Compute product of two quaternions"""
    p0 = p[0]; p = p[1:4]
    q0 = q[0]; q = q[1:4]
    pq0 = p0*q0 - np.dot(p, q)
    pq = p0*q + p*q0 + np.cross(p,q)
    return np.concatenate([[pq0], pq])

def euler2quat(phi, theta, psi):
    psi2 = psi/2
    theta2 = theta/2
    phi2 = phi/2
    return np.array([
        np.sin(phi2)*np.sin(psi2)*np.sin(theta2) + np.cos(phi2)*np.cos(psi2)*np.cos(theta2),
        np.sin(phi2)*np.cos(psi2)*np.cos(theta2) - np.sin(psi2)*np.sin(theta2)*np.cos(phi2),
        np.sin(phi2)*np.sin(psi2)*np.cos(theta2) + np.sin(theta2)*np.cos(phi2)*np.cos(psi2),
        -np.sin(phi2)*np.sin(theta2)*np.cos(psi2) + np.sin(psi2)*np.cos(phi2)*np.cos(theta2)
        ])

def quat2rot(q):
    """Compute rotation matrix from quaternion.
    quaternion must be provided in form [q0, q]
    """
    q = q.flatten()
    q0 = q[0]
    q = q[1:]
    return (q0**2 - np.dot(q, q))*np.eye(3) + 2*np.outer(q,q) + 2*q0*skew(q)

def quat2euler(q):
    R = quat2rot(q)
    return rot2euler(R)

if __name__ == "__main__":
    # Tests

    # Check quat_prod
    p = np.array([3, 1, -2, 1])
    q = np.array([2, -1, 2, 3])
    pq = np.array([8, -9, -2, 11])
    print('pq_hand - pq = ', np.linalg.norm(prod(p,q)-pq))

    # Check conversions rot <-> quat
    phi = 2*np.pi * np.random.random_sample()
    theta = 2*np.pi * np.random.random_sample()
    psi = 2*np.pi * np.random.random_sample()
    R = euler2rot(phi=phi, theta=theta, psi=psi)
    q = euler2quat(phi=phi, theta=theta, psi=psi)
    R_ = quat2rot(q)
    print('R - R_ = ',np.linalg.norm(R-R_))

    # Check defs w and qdot
    w = np.random.rand(4); w[0]=0
    qdot = 0.5 * prod(q, w)
    qc = conj(q)
    w_ = 2 * prod(qc, qdot)
    print('w - w_ = ', np.linalg.norm(w-w_))

    phi_, theta_, psi_ = quat2euler(q)
    print("phi - phi_ = ", phi - phi_)
    print("theta - theta_ = ", theta - theta_)
    print("psi - psi_ = ", psi - psi_)


from sympy import *
from difference_quotient import difference_quotient
import numpy as np

def spline3_interpolate(points: list, simplify_result=True):
    """三弯矩法插值

    三弯矩法进行三次样条插值。使用自由边界条件。

    Args:
        points: list, [(x1, y1), (x2, y2), ..., (xn, yn)]
        simplify_result: bool, 化简最终结果, default True

    Returns:
        L: sympy Piecewise object of Symbol('x'), 插值多项式 $L(x)$
    """
    # 排序给定的点
    ps = sorted(points, key=lambda p: p[0])
    n = len(points)

    # points to a function
    _f_dict = dict(ps)

    def f(x):
        return _f_dict[x]

    # $h_k = x_{k+1} - x_k$
    def h(k):
        return ps[k+1][0] - ps[k][0]

    hks = [h(0)]

    # 用方程 D * M = d 解出 M

    D = np.zeros((n, n))
    d = np.zeros(n)

    for k in range(1, n-1):
        # $h_k$, $h_{k-1}$
        hks.append(h(k))
        hk, hks1 = hks[k], hks[k-1]

        # $\mu_k$ -> mu, $\lambda_k$ -> ld
        _fra = hks1 + hk
        mu = hks1 / _fra
        ld = hk / _fra

        # $\mu_kM_{k-1}+2M_k+\lambda_kM_{k+1} = d_k$
        D[k, k-1] = mu
        D[k, k] = 2
        D[k, k+1] = ld
        d[k] = 6 * difference_quotient(f, [ps[k-1][0], ps[k][0], ps[k+1][0]])

    # 边界条件
    # Natural Boundary
    D[0, 0] = 1
    D[n-1, n-1] = 1

    d[0] = 0
    d[n-1] = 0

    # 解出 M
    M = np.linalg.solve(D, d)

    # 插值函数
    piecewises = []
    for k in range(n-1):
        s = M[k] * (ps[k+1][0] - _x) ** 3 / (6 * hks[k])
        s += M[k+1] * (_x - ps[k][0]) ** 3 / (6 * hks[k])
        s += (ps[k][1] - M[k] * hks[k]**2 / 6) * (ps[k+1][0] - _x) / hks[k]
        s += (ps[k+1][1] - M[k+1] * hks[k]**2 / 6) * (_x - ps[k][0]) / hks[k]
        if simplify_result:
            s = simplify(s)
        piecewises.append((s, And(_x >= ps[k][0], _x <= ps[k+1][0])))

    return Piecewise(*piecewises)


import numpy as np
# Setting the random seed, feel free to change it and see different solutions.
np.random.seed(42)

def sigmoid(x):
    return 1/(1+np.exp(-x))
def sigmoid_prime(x):
    return sigmoid(x)*(1-sigmoid(x))
def prediction(X, W, b):
    return sigmoid(np.matmul(X,W)+b)
def error_vector(y, y_hat):
    return [-y[i]*np.log(y_hat[i]) - (1-y[i])*np.log(1-y_hat[i]) for i in range(len(y))]
def error(y, y_hat):
    ev = error_vector(y, y_hat)
    return sum(ev)/len(ev)

def dErrors(X, y, y_hat):
    dErrs = []
    yDiff = [(y_hat[i] - y[i]) for i in range(len(y))]
    # With respect to all wi
    for j in range(len(X[0])):
        dErrs.append([X[i][j] * yDiff[i]  for i in range(len(y))])
    # with respect to b
    dErrs.append(yDiff)
    return dErrs

def gradientDescentStep(X, y, W, b, learn_rate = 0.01):
    y_hat = prediction(X,W,b)
    e = sum(error_vector(y, y_hat))
    gradient = dErrors(X, y, y_hat)
    W = [W[i]-sum(gradient[i]) * learn_rate for i in range(len(W))]
    b -= sum(gradient[2])*learn_rate
    return W, b, e

# This function runs the perceptron algorithm repeatedly on the dataset,
# and returns a few of the boundary lines obtained in the iterations,
# for plotting purposes.
# Feel free to play with the learning rate and the num_epochs,
# and see your results plotted below.
def trainLR(X, y, learn_rate = 0.01, num_epochs = 100):
    x_min, x_max = min(X.T[0]), max(X.T[0])
    y_min, y_max = min(X.T[1]), max(X.T[1])
    # Initialize the weights randomly
    W = np.array(np.random.rand(2,1))*2 -1
    b = np.random.rand(1)[0]*2 - 1
    # These are the solution lines that get plotted below.
    boundary_lines = []
    errors = []
    for i in range(num_epochs):
        # In each epoch, we apply the gradient descent step.
        W, b, error = gradientDescentStep(X, y, W, b, learn_rate)
        boundary_lines.append((-W[0]/W[1], -b/W[1]))
        errors.append(error)
    return boundary_lines, errors


"""
Authors: Luiz Gustavo Mugnaini Anselmo (nUSP: 11809746)
         Victor Manuel Dias Saliba     (nUSP: 11807702)
         Luan Marc Suquet Camargo      (nUSP: 11809090)

Computacao III (CCM): Ep 3 QR factorization
"""
import math
import numpy as np

class RealSpace:
    """Real Space methods"""

    @classmethod
    def inner_product(cls, v: np.ndarray, u: np.ndarray) -> float:
        """Standard real dot product `v` * `u`"""
        if v.size != u.size:
            raise Exception("Vectors have different length")
        return sum(x * y for x, y in zip(v, u))

    @classmethod
    def norm(cls, v: np.ndarray) -> float:
        """Norm of given vector `v`"""
        return math.sqrt(cls.inner_product(v, v))

    @classmethod
    def distance(cls, v: np.ndarray, u: np.ndarray) -> float:
        """Distance between vectors `v` and `u`"""
        return math.sqrt(cls.inner_product(v, u))

    @classmethod
    def proj(cls, v: np.ndarray, u: np.ndarray) -> np.ndarray:
        """Projection of `v` in `u`"""
        return cls.inner_product(u, v) / cls.inner_product(u, u) * u

    @classmethod
    def gram_schmidt(cls, set: list[np.ndarray]) -> list[np.ndarray]:
        """Gram-Schmidt algorithm.
        Takes a list of vectors (`set`) and applies the method of Gram-Schmidt,
        orthonormalizing `set`.
        """
        # Orthogonalization algorithm
        ortho: list[np.ndarray] = [np.copy(set[0]) / cls.norm(set[0])]
        for j in range(1, len(set)):
            q = np.copy(set[j])
            for i in range(j):
                r = cls.inner_product(set[j], ortho[i])
                q -= r * ortho[i]

            # Check if the list is LI and, if so, append the normalized vector
            norm = cls.norm(q)
            if norm == 0:
                raise Exception("The list of vectors is linearly dependent.")
            ortho.append(q / norm)

        return ortho


import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_blobs

class KMeans:

    def __init__(self , k , nbr_iterations = 500):
        self.k = k
        self.nbr_iterations = nbr_iterations
        self.clusters = [[] for i in range(self.k)]
        self.centers = []

    def fit(self , x):
        self.x = x
        self.nbr_samples , self.nbr_features = x.shape

        #initialize The Centers Randomly
        centers_indexes = np.random.choice(self.nbr_samples , self.k , replace = False)
        self.centers = [self.x[index] for index in centers_indexes]

        for i in range(self.nbr_iterations):

            #Assign Samples to the clossest Center
            self.clusters = self.CreateClusters(self.centers)

            oldCenters = self.centers
            self.centers = self.UpdateCenters(self.clusters)

            #Check if The Stoping Criteria is True
            if self.StopingCriteria(oldCenters , self.centers):
                break

    def CreateClusters(self , centers):
        CurrentClusters = [[] for i in range(self.k)]

        for index , sample in enumerate(self.x):
            clossestCenter = self.clossest_center(sample , centers)
            CurrentClusters[clossestCenter].append(index)
        return CurrentClusters

    def clossest_center(self , sample , centers):
        distances = [self.euclideanDistance(sample, center) for center in centers]
        return np.argmin(distances)

    def UpdateCenters(self , clusters):
        newCenters = np.zeros((self.k , self.nbr_features))
        for index , cluster in enumerate(clusters):
            center = np.mean(self.x[cluster] , axis = 0)
            newCenters[index] = center
        return newCenters

    def StopingCriteria(self , oldCenters , newCenters):
        distances = [self.euclideanDistance(oldCenters[i], newCenters[i]) for i in range(self.k)]
        return sum(distances) == 0

    def getClusters(self):
        labels = np.empty(self.nbr_samples)

        for index , cluster in enumerate(self.clusters):
            for sampleIndex in cluster:
                labels[sampleIndex] = index
        return labels

    def displayTheResult(self):

        fig, ax = plt.subplots(figsize=(12, 8))
        #display The Clusters
        for _ , index in enumerate(self.clusters):
            points = self.x[index]
            ax.scatter(points[:,0] , points[:,1])
        #display The Centers
        for center in self.centers:
            ax.scatter(center[0] , center[1], marker="x", color="black", linewidth=5)
        plt.title("KMeans")
        plt.show()

    def euclideanDistance(self , x1 , x2):
        return np.sqrt(np.sum( (x1 - x2)**2 ))

#Test K-Means
def accuracy(y_true , y_pred):
    return np.sum(y_true == y_pred) / len(y_true)

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

nbr_classes = len(np.unique(y))
K_means = KMeans(k = nbr_classes)
K_means.fit(x)
y_pred = K_means.getClusters()
K_means.displayTheResult()
print("KMeans Accuracy : ",accuracy(y, y_pred))


import numpy as np
import matplotlib.pylab as plt

# sigmoid function used broadcast for numpy array.
def sigmoid(x):
    return 1 / (1 + np.exp(-x))

a = np.array([-1.0, 1.0, 2.0])

print(sigmoid(a))

# 이와 같은 시그모이드 함수를 그래프로 나타내 그 변화를 살펴보자.

x = np.arange(-5.0, 5.0, 0.1)
y = sigmoid(x)
plt.plot(x, y)
plt.ylim(-0.1, 1.1) # y축의 범위 지정
plt.show()


# To add a new cell, type '#%%'
# To add a new markdown cell, type '#%% [markdown]'
#%%
from IPython import get_ipython

#%%
import numpy as np

#%%
list1 = [1, 3, 4, 5]
a = np.array(list1)
a

#%%
type(a)

#%%
a.dtype

#%%
a.size

#%%
a.ndim

#%%
a.shape

#%%
b = np.array([23, 7.4, 11, 98, 54, 23.67])
type(b)

#%%
b.ndim

#%%
b.size

#%%
b.shape

#%% [markdown]
# ## Indexing and Slicing

#%%
c = np.array([22, 56, 98, 54, 21])
c

#%%
#assign 56 to 34
c[1] = 34
c

#%%
# slicing
d = c[1:3]
d

#%%
d[0:2] = 66, 77
d

#%% [markdown]
# ## Basic operation
#%% [markdown]
# ### Vector Addition and subtraction

#%%
v1 = np.array([0, 1])
v2 = np.array([1, 0])
v1 + v2

#%%
## anothr way
u = np.array([1, 0])
v = np.array([0, 1])
z = []

for n,m in zip(u, v):
    z.append(n+m)
z

#%% [markdown]
# ### Array multiplication with scaler

#%%
y = np.array([1, 2])
z = 2*y
z

#%%
## another way
zz = []
for n in y:
    zz.append(2*n)
zz

#%% [markdown]
# ### Product of two vectors

#%%
tt1 = np.array([1, 2])
tt2 = np.array([3, 4])

tt = tt1 * tt2
tt

#%%
## another way
tt3 = []
for n,m in zip(tt1, tt2):
    tt3.append(n*m)
tt3

#%% [markdown]
# ### Dot product

#%%
ff1 = np.array([1, 2])
ff2 = np.array([3, 4])

result = np.dot(ff1, ff2)
result

#%%
## another way
result2 = []
for n,m in zip(ff1, ff2):
    result2.append(np.dot(n, m))
result2

#%% [markdown]
# ### Adding constant to numpy array
#%% [markdown]
#

#%%
gg = np.array([2, 3, 4, -9])
res1 = gg + 1
res1

#%% [markdown]
# ## Universal Function

#%%
fg = np.array([3, 5, 7, 9])

#%%
fg.mean()

#%%
fg.max()

#%%
fg.min()

#%%
## pi value
np.pi

#%%
# np.sin(x)
#
#

#%%
# starting value = -2 and ending value= 2 total values 5
np.linspace(-2, 2, num=5)

#%%
np.linspace(-2, 2, num=9)

#%%
## plotting mathamatical function
x = np.linspace(0, 2*np.pi, 50)
x

#%%
y = np.sin(x)
y

#%%
import matplotlib.pyplot as plt

#%%
get_ipython().run_line_magic('matplotlib', 'inline')
plt.plot(x, y)
#first input x is horizontal axis
#second element y is vertical axis

#%% [markdown]
# # Two Dimenstional Array

#%%
a = np.array([[1, 2, 3], [11, 12, 13], [21, 22, 23], [31, 32, 33]])

#%%
a.ndim

#%%
a.shape

#%%
a.size

#%%
# to access first row 3rd element
a[0][2]

#%%
# alternate
a[0, 2]

#%%
## slicing in numpy array
a[0, 0:2]

#%%
## adding as matrix
as1 = np.array([
    [1, 2, 3, 4],
    [2, 4, 6, 8],
    [1, 3, 5, 7]
])
as2 = np.array([
    [1, 2, 3, 4],
    [2, 4, 6, 8],
    [1, 3, 5, 7]
])

#%%
as1 + as2

#%%
as1.ndim

#%%
as1

#%%
as1 * 2

#%%
# matrix multiplication is littile bit complex
# matrix A rows must b equal to matrix B column
# each element of A is multiply with all element of B column

#%%
dfA = np.array([[1, 2, 3], [2, 0, 1]])
dfB = np.array([[1, 2], [0, 1], [3, 4]])

#%%
dfZ = np.dot(dfA, dfB)

#%%
dfZ

#%%
X=np.array([[1,0],[0,1]])
Y=np.array([[2,2],[2,2]])
Z=np.dot(X,Y)
Z

#%%


from __future__ import division
import numpy
import scipy.integrate
import matplotlib.pyplot as pyplot

USER = 'Maciej Grabias'
USER_ID = 'njgh39'

r = 0.15 # radius of the cannonball in meters
rho_iron =  7874.00 # density of iron in kg m-3
g =  9.81 # acceleration due to gravity in ms-2
kappa =  0.47 # drag coefficient of a sphere
rho_air =  1.23 # density of air in kg m-3
t1 =  25.00 # end time for our ODE integration in s
v0 = 125.00 # launch speed in m s-1
n_panels =  400 # the number of panels to use

# cross section area & mass of cannonball determined using above

area = numpy.pi* r**2
mass = rho_iron * (4/3) * numpy.pi * r**3

# define the function
def f((x, y, vx, vy),t):

    # gravitational forces
    Fx_grav = 0
    Fy_grav = - mass * g

    # drag forces
    Fx_drag = - kappa * rho_air * area * v0 * vx
    Fy_drag = - kappa * rho_air * area * v0 * vy

    d_x = vx # dx/dt
    d_y = vy # dy/dt
    d_vx =  Fx_drag / mass # dvx/dt
    d_vy = (Fy_drag + Fy_grav) / mass # dvy/dt

    return numpy.array((d_x, d_y, d_vx, d_vy))

def solve_euler(state, t1, n_panel):

    history = numpy.zeros((n_panels, len(state)))
    dt = t1 / n_panels

    # integrate with Euler method
    for i in range(n_panels):
        history[i] = state
        state = state + f(state, dt * i) * dt
    return history

# define timebase
timebase = numpy.arange(0, t1, t1 / n_panels)

def trim_trajectory(values):

    # process trajectory to terminate when below y = 0
    for i in range(len(values) - 1):
        x0, y0, vx0, vy0 = values[i]
        x1, y1, vx1, vy1 = values[i + 1]
        if y0 < 0: return values[:i]
    return values

proj_range = []
thetas = range(5,90,5)

pyplot.subplot(211)

for theta in thetas:

    vx, vy = numpy.cos(numpy.deg2rad(theta)) * v0, numpy.sin(numpy.deg2rad(theta)) * v0
    initial_conditions = (0, 0, vx, vy)

    values_scipy = scipy.integrate.odeint(f, initial_conditions, timebase)
    values_euler = solve_euler(initial_conditions, t1, n_panels)
    values_scipy = trim_trajectory(values_scipy)
    values_euler = trim_trajectory(values_euler)

    # calculate range

    x_first, y_first, vx_first, vy_first = values_scipy[0]
    x_final, y_final, vx_final, vy_final = values_scipy[-1]

    rnge = x_final - x_first

    proj_range.append(rnge)

    # trajectory for scipy integrate
    x_scipy = values_scipy[:, 0]
    y_scipy = values_scipy[:, 1]

    # trajectory for Euler integrate
    x_euler = values_euler[:,0]
    y_euler = values_euler[:,1]

    # plot trajectories
    pyplot.plot(x_scipy, y_scipy, color = 'grey', label = "Odeint")
    pyplot.plot(x_euler, y_euler, color = 'blue', linestyle = '--', label = "Euler")
    pyplot.title("Trajectories for Euler & Odeint Methods")
    pyplot.xlabel("X coordinate")
    pyplot.ylabel("Y coordinate")

pyplot.legend(("Odeint", "Euler"))

# plot range VS launch angle
pyplot.subplot(212)
pyplot.plot(thetas, proj_range, color = 'red')
pyplot.title("Range VS Launch Angle")
pyplot.xlabel("Launch Angle, deg")
pyplot.ylabel("Range, m")

pyplot.show()

ANSWER1 = """ The angle from the horizontal for maximum range under these
conditions is 40 degrees."""
ANSWER2 = """ The angle decreases with increasing air density """


# solutions.py
"""Volume 1, Lab 16: Importance Sampling and Monte Carlo Simulations.
Solutions file. Written by Tanner Christensen, Winter 2016.
"""

from __future__ import division
import matplotlib.pyplot as plt
import numpy as np
import scipy.stats as stats

def prob1(n):
    """Approximate the probability that a random draw from the standard
    normal distribution will be greater than 3."""
    h = lambda x : x > 3
    X = np.random.randn(n)
    return 1/n * np.sum(h(X))

def prob2():
    """Answer the following question using importance sampling:
            A tech support hotline receives an average of 2 calls per
            minute. What is the probability that they will have to wait
            at least 10 minutes to receive 9 calls?
    Returns:
        IS (array) - an array of estimates using
            [5000, 10000, 15000, ..., 500000] as number of
            sample points."""
    h = lambda y : y > 10
    f = lambda y : stats.gamma(a=9,scale=0.5).pdf(y)
    g = lambda y : stats.norm(loc=12,scale=2).pdf(y)
    num_samples = np.arange(5000,505000,5000)
    IS = []
    for n in num_samples:
        Y = np.random.normal(12,2,n)
        approx = 1./n*np.sum(h(Y)*f(Y)/g(Y))
        IS.append(approx)
    IS = np.array(IS)
    return IS

def prob3():
    """Plot the errors of Monte Carlo Simulation vs Importance Sampling
    for the prob2()."""
    h = lambda x : x > 10
    MC_estimates = []
    for N in xrange(5000,505000,5000):
        X = np.random.gamma(9,scale=0.5,size=N)
        MC = 1./N*np.sum(h(X))
        MC_estimates.append(MC)
    MC_estimates = np.array(MC_estimates)

    IS_estimates = prob2()

    actual = 1 - stats.gamma(a=9,scale=0.5).cdf(10)

    MC_errors = np.abs(MC_estimates - actual)
    IS_errors = np.abs(IS_estimates - actual)

    x = np.arange(5000,505000,5000)
    plt.plot(x, MC_errors, color='r', label="Monte Carlo")
    plt.plot(x, IS_errors, color='b', label="Importance Sampling")
    plt.legend()
    plt.show()

def prob4():
    """Approximate the probability that a random draw from the
    multivariate standard normal distribution will be less than -1 in
    the x-direction and greater than 1 in the y-direction."""
    h = lambda y : y[0] < -1 and y[1] > 1
    f = lambda y : stats.multivariate_normal(np.zeros(2), np.eye(2)).pdf(y)
    g = lambda y : stats.multivariate_normal(np.array([-1,1]), np.eye(2)).pdf(y)

    n = 10**4
    Y = np.random.multivariate_normal(np.array([-1,1]), np.eye(2), size=n)
    hh = np.apply_along_axis(h, 1, Y)
    ff = np.apply_along_axis(f, 1, Y)
    gg = np.apply_along_axis(g, 1, Y)
    approx = 1./n*np.sum(hh*ff/gg)

    return approx

if __name__ == "__main__":
    import numpy as np
    print prob4()

    n = 10**6
    h = lambda y : y[0] < -1 and y[1] > 1
    X = np.random.multivariate_normal(np.zeros(2),np.eye(2),n)
    print 1/n * np.sum(np.apply_along_axis(h, 1, X))


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

"""
Funcție care caută intervalele pe care funcția are o soluție.
f(a) * f(b) < 0 -> EXISTENȚA
"""
def cauta_intervale(f, a, b, n):
    """
    Parameters
    ----------
    f : funcția asociată ecuației f(x)=0.
    a : capătul din stânga interval.
    b : capătul din dreapta interval.
    n : nr de subintervale în care împărțim intervalul global (a, b).

    Returns
    -------
    Matricea 'intervale' cu 2 linii; prima linie -> capăt st interval curent
    si a doua linie -> capat dr
    si un nr de coloane = nr radacini
    """

    x = np.linspace(a, b, n+1)   #returnează n+1 numere, situate la distanțe egale, din cadrul intervalului [a, b]
    for i in range(len(x)):   #range: for i = 0, len(x); i++
        if(f(x[i]) == 0):     #capetele intervalelor mele nu au voie să fie 0; tb să avem soluțiile în intervale, nu la capete
            print("Schimba nr de Intervale")
            exit(0)

    matrice = np.zeros((2, 1000))  #returnează un nou vector plin de 0; pt că am (2, 1000) -> matrice cu 2 rânduri și 1000 coloane
    z = 0
    for i in range(n):
        if f(x[i]) * f(x[i+1]) < 0:  #existență soluție
            matrice[0][z] = x[i]
            matrice[1][z] = x[i + 1]
            z += 1

    matrice_finala = matrice[:, 0:z]   #iei ambele 2 linii și doar coloanele de la 0 la z (numărat mai sus)
    return matrice_finala

"""
    Funcție care implementează algoritmul metodei bisecției.
"""
def bisectie(f, xmin, xmax, eps):
    """
    Parameters
    ----------
    f : f(x) = 0.
    xmin, xmas: capete intervale.
    eps : toleranța / eroarea (epsilon).

    Returns
    -------
    Soluția aproximativă, dar și numărul de iterații N necesar pt a obține soluția cu eroarea eps.
    """

    c = (xmin + xmax) / 2
    N = np.floor(np.log2((xmax-xmin)/eps))  #floor: cel mai mare int, dar mai mic decât val. mea
    for i in range(int(N)):
        if f(c) == 0:
            break                           #am gasit soluția
        elif f(xmin) * f(c) < 0:
            xmax = c
        elif f(xmin) * f(c) > 0:
            xmin = c

        c = (xmin + xmax) / 2
    return c, N

"""
    Funcție care implementează algoritmul metodei bisecției.
    ---> Pt Lab2.Ex4.
"""
def bisectie2(f, xmin, xmax, eps):

    x_old = (xmin + xmax) / 2
    k = 1
    while True:
        if f(x_old) == 0:
            x_new = x_old
            break
        elif f(xmin) * f(x_old) < 0:
            xmax = x_old
        elif f(xmin) * f(x_old) > 0:
            xmin = x_old

        x_new = (xmin + xmax) / 2
        k += 1
        if abs(x_new - x_old) / abs(x_old) < eps:
            break
        x_old = x_new

    return x_new, k

"""
    Metoda Newton-Raphson
"""
def NewtonRap(f, df, x0, eps):
    """
    Parameters
    ----------
    f : functia pt care cautam solutia f(x) = 0.
    df : derivata functiei.
    x0 : valoare de pornire.
    eps : epsilon / toleranta.

    Returns
    -------
    solutia (xk), nr de iteratii (N).
    """

    x_old = x0
    N = 1
    while True:
        #Calculăm noua iteratie
        x_new = x_old - (f(x_old) / df(x_old))
        N += 1
        if(abs(x_new - x_old) / abs(x_old) < eps):
            break
        x_old = x_new

    return x_new, N

Calcul Numeric (CN)/Laborator/Laborator 1, 2/metode_numerice_ecuatii_algebrice.py


import matplotlib.pyplot as plt
import numpy as np
from scipy.fftpack import fft, ifft

N = 256
M = 63
f0 = 1000
fs = 10000
A0 = .8
hN = N//2
hM = (M+1)//2
fftbuffer = np.zeros(N)
X1 = np.zeros(N, dtype='complex')
X2 = np.zeros(N, dtype='complex')

x = A0 * np.cos(2*np.pi*f0/fs*np.arange(-hM+1,hM))

plt.figure(1, figsize=(9.5, 7))
w = np.hanning(M)
plt.subplot(2,3,1)
plt.title('w (hanning window)')
plt.plot(np.arange(-hM+1, hM), w, 'b', lw=1.5)
plt.axis([-hM+1, hM, 0, 1])

fftbuffer[:hM] = w[hM-1:]
fftbuffer[N-hM+1:] = w[:hM-1]
X = fft(fftbuffer)
X1[:hN] = X[hN:]
X1[N-hN:] = X[:hN]
mX = 20*np.log10(abs(X1))

plt.subplot(2,3,2)
plt.title('mW')
plt.plot(np.arange(-hN, hN), mX, 'r', lw=1.5)
plt.axis([-hN,hN,-40,max(mX)])

pX = np.angle(X1)
plt.subplot(2,3,3)
plt.title('pW')
plt.plot(np.arange(-hN, hN), np.unwrap(pX), 'c', lw=1.5)
plt.axis([-hN,hN,min(np.unwrap(pX)),max(np.unwrap(pX))])

plt.subplot(2,3,4)
plt.title('xw (windowed sinewave)')
xw = x*w
plt.plot(np.arange(-hM+1, hM), xw, 'b', lw=1.5)
plt.axis([-hM+1, hM, -1, 1])

fftbuffer = np.zeros(N)
fftbuffer[0:hM] = xw[hM-1:]
fftbuffer[N-hM+1:] = xw[:hM-1]
X = fft(fftbuffer)
X2[:hN] = X[hN:]
X2[N-hN:] = X[:hN]
mX2 = 20*np.log10(abs(X2))

plt.subplot(2,3,5)
plt.title('mXW')
plt.plot(np.arange(-hN, hN), mX2, 'r', lw=1.5)
plt.axis([-hN,hN,-40,max(mX)])

pX = np.angle(X2)
plt.subplot(2,3,6)
plt.title('pXW')
plt.plot(np.arange(-hN, hN), np.unwrap(pX), 'c', lw=1.5)
plt.axis([-hN,hN,min(np.unwrap(pX)),max(np.unwrap(pX))])

plt.tight_layout()
plt.savefig('sine-spectrum.png')
plt.show()