from inspect import signature
import numpy as np
import logging
from mpl_toolkits import mplot3d

def df_dx(func, epsilon=1e-3):
	nargs = len(signature(func).parameters)
	# 3D function
	if nargs == 2:
		return lambda x, y: ((func(x + epsilon, y) - func(x, y)) / epsilon)
	# 2D function
	if nargs == 1:
		return lambda x: ((func(x + epsilon) - func(x)) / epsilon)
	logging.error('Cannot work on functions with more than 2 variables')

def df_dy(func, epsilon=1e-3):
	return lambda x, y: ((func(x, y + epsilon) - func(x, y)) / epsilon)

def df_dxdx(func):
	nargs = len(signature(func).parameters)
	# 3D function
	if nargs == 2:
		return lambda x, y: df_dx(df_dx(func))(x, y)
	# 2D function
	if nargs == 1:
		return lambda x: df_dx(df_dx(func))(x)
	logging.error('Cannot work on functions with more than 2 variables')

def df_dydy(func):
	return lambda x, y: df_dy(df_dy(func))(x, y)

def df_dxdy(func):
	return lambda x, y: df_dx(df_dy(func))(x, y)

def df_dydx(func):
	return lambda x, y: df_dy(df_dx(func))(x, y)

def grad(func):
	nargs = len(signature(func).parameters)
	if nargs == 2:
		return lambda x, y: np.array([df_dx(func)(x, y), df_dy(func)(x, y)])
	logging.error('Cannot calculate gradient, function is not 3D')

def hess(func):
	nargs = len(signature(func).parameters)
	if nargs == 2:
		return lambda x, y: np.array([[df_dxdx(func)(x, y), df_dxdy(func)(x, y)],
		                              [df_dydx(func)(x, y), df_dydy(func)(x, y)]])
	logging.error('Cannot calculate hessian, function is not 3D')

def newton(func, x0=(0, 0), steps=2, delta=.05):
	nargs = len(signature(func).parameters)

	# 3D function
	if nargs == 2:
		res = np.array([x0[0], x0[1]])
		gradient = grad(func)
		hessian = hess(func)

		for i in range(steps):
			gd = gradient(res[0], res[1])
			hs = hessian(res[0], res[1])
			inverse = np.linalg.inv(hs)
			prev = res
			res = prev - (np.dot(gd, inverse))
			diff = abs(func(res[0], res[1]) - func(prev[0], prev[1]))
			if diff < delta:
				break

	# 2D function
	elif nargs == 1:
		res = x0
		dx = df_dx(func)
		dxdx = df_dxdx(func)

		for i in range(steps):
			prev = res
			res = prev - dx(prev) / dxdx(prev)
			diff = abs(prev - res)
			if diff < delta:
				break

	return res

def plot(func, start=-10, end=10, bins=100, savefig=False, plotfunc=True, plotgrad=True, filename=''):
	from matplotlib import pyplot as plt
	nargs = len(signature(func).parameters)
	x = np.linspace(start, end, bins)

	# if given function is 2D
	if nargs == 1:
		X = np.linspace(start, end, bins)
		Y = func(X)
		dx = df_dx(func)(X)
		dxdx = df_dxdx(func)(X)

		fig = plt.figure(figsize=(8, 6))
		ax = fig.add_subplot(2, 2, 1, title='f(x)')
		ax.set_xlabel('x')
		ax.set_ylabel('y')
		ax.plot(Y)
		b = fig.add_subplot(2, 2, 2, title='f\'(x)')
		b.set_xlabel('x')
		b.set_ylabel('y')
		b.plot(dx)
		c = fig.add_subplot(2, 2, 3, title='f\'\'(x)')
		c.set_xlabel('x')
		c.set_ylabel('y')
		c.plot(dxdx)

	# 3D function
	elif nargs == 2:
		y = np.linspace(start, end, bins)

		X, Y = np.meshgrid(x, y)
		gradient = grad(func)
		gd = gradient(X, Y)
		Z = func(X, Y)

		fig = plt.figure(figsize=(8, 6))
		if plotfunc and plotgrad:
			ax = fig.add_subplot(1, 2, 1, projection='3d', title='f(x,y)', adjustable='box', aspect=1)
			ax.contour3D(X, Y, Z, 50, cmap='binary')
			ax.set_xlabel('x')
			ax.set_ylabel('y')
			ax.set_zlabel('z')
			b = fig.add_subplot(1, 2, 2, title='gradient', adjustable='box', aspect=1)
			b.quiver(X, Y, gd[0], gd[1])

		elif plotfunc:
			ax = fig.add_subplot(1, 1, 1, projection='3d', title='f(x,y)', adjustable='box', aspect=1)
			ax.contour3D(X, Y, Z, 50, cmap='binary')
			ax.set_xlabel('x')
			ax.set_ylabel('y')
			ax.set_zlabel('z')

		elif plotgrad:
			b = fig.add_subplot(1, 1, 1, title='gradient', adjustable='box', aspect=1)
			b.quiver(X, Y, gd[0], gd[1])

	plt.show()

	if savefig and plotfunc or plotgrad:
		if plotfunc and plotgrad:
			filename = 'plot'
		elif plotfunc:
			filename = 'function'
		elif plotgrad:
			filename = 'gradient'

		logging.info('saving plot as svg...')
		fig.savefig(filename + '.svg')

if __name__ == '__main__':
	np.set_printoptions(precision=3)
	print(newton(lambda x, y: 2 * (x ** 2) + (x * y) + 2 * ((y - 3) ** 2), (-1, 4)))
	plot(lambda x, y: 2 * (x ** 2) + (x * y) + 2 * ((y - 3) ** 2), plotfunc=False)
	plot(lambda x, y: 2 * (x ** 2) + (x * y) + 2 * ((y - 3) ** 2), plotgrad=False)
	print('%.2f' % newton(lambda x: x ** 2, 2))
	plot(lambda x: x ** 2)


from sympy import cancel, expand, gcd_list, symbols
from homogeneous import *

def circle(P1, P2, P3):
    # return (a, d, e, f) such that a*x**2 + a*y**2 + d*x*z + e*y*z + f*z**2 = 0 is the circle's equation
    x, y, z = symbols('x, y, z')
    x1, y1, z1, x2, y2, z2, x3, y3, z3 = P1[0], P1[1], P1[2], P2[0], P2[1], P2[2], P3[0], P3[1], P3[2]
    # generated by homogeneous-circle.py
    a = expand(x1*y2*z1*z2*z3**2 - x1*y3*z1*z2**2*z3 - x2*y1*z1*z2*z3**2 + x2*y3*z1**2*z2*z3 + x3*y1*z1*z2**2*z3 - x3*y2*z1**2*z2*z3)
    d = expand(-x1**2*y2*z2*z3**2 + x1**2*y3*z2**2*z3 + x2**2*y1*z1*z3**2 - x2**2*y3*z1**2*z3 - x3**2*y1*z1*z2**2 + x3**2*y2*z1**2*z2 - y1**2*y2*z2*z3**2 + y1**2*y3*z2**2*z3 + y1*y2**2*z1*z3**2 - y1*y3**2*z1*z2**2 - y2**2*y3*z1**2*z3 + y2*y3**2*z1**2*z2)
    e = expand(x1**2*x2*z2*z3**2 - x1**2*x3*z2**2*z3 - x1*x2**2*z1*z3**2 + x1*x3**2*z1*z2**2 - x1*y2**2*z1*z3**2 + x1*y3**2*z1*z2**2 + x2**2*x3*z1**2*z3 - x2*x3**2*z1**2*z2 + x2*y1**2*z2*z3**2 - x2*y3**2*z1**2*z2 - x3*y1**2*z2**2*z3 + x3*y2**2*z1**2*z3)
    f = expand(-x1**2*x2*y3*z2*z3 + x1**2*x3*y2*z2*z3 + x1*x2**2*y3*z1*z3 - x1*x3**2*y2*z1*z2 + x1*y2**2*y3*z1*z3 - x1*y2*y3**2*z1*z2 - x2**2*x3*y1*z1*z3 + x2*x3**2*y1*z1*z2 - x2*y1**2*y3*z2*z3 + x2*y1*y3**2*z1*z2 + x3*y1**2*y2*z2*z3 - x3*y1*y2**2*z1*z3)
    gcd = gcd_list([a, d, e, f])
    return cancel(a/gcd), cancel(d/gcd), cancel(e/gcd), cancel(f/gcd)

def on_circle(C, P):
    a, d, e, f, x, y, z = C[0], C[1], C[2], C[3], P[0], P[1], P[2]
    return expand(a*(x**2 + y**2) + d*x*z + e*y*z + f*z**2) == 0

def perpendicular(A, B, P):
    # return (u, v, w) such that u*x + v*y + w*z = 0 is perpendicular to AB and passes through P
    x1, y1, z1, x2, y2, z2, x3, y3, z3 = A[0], A[1], A[2], B[0], B[1], B[2], P[0], P[1], P[2]
    u, v = x1*z2 - x2*z1, y1*z2 - y2*z1
    return reduced(u*z3, v*z3, -u*x3 - v*y3)

def intersect(C1, C2, P1):
    # return another intersection P2 of circles C1 and C2
    assert on_circle(C1, P1) and on_circle(C2, P1)
    CC1, CC2 = reduced(-C1[1], -C1[2], 2*C1[0]), reduced(-C2[1], -C2[2], 2*C2[0])
    C1C2, P1P2 = cross(CC1, CC2), perpendicular(CC1, CC2, P1)
    M = cross(C1C2, P1P2)
    x1, y1, z1, x2, y2, z2 = P1[0], P1[1], P1[2], M[0], M[1], M[2]
    P2 = reduced(2*x2*z1 - x1*z2, 2*y2*z1 - y1*z2, z1*z2)
    assert on_circle(C1, P2) and on_circle(C2, P2)
    return P2

def circle_eq(C):
    return f'({C[0]})*x**2 + ({C[0]})*y**2 + ({C[1]})*x*z + ({C[2]})*y*z + ({C[3]})*z**2 = 0'

def main():
    # https://en.wikipedia.org/wiki/Five_circles_theorem
    a, b, c, d, e, f, g = symbols('a, b, c, d, e, f, g')
    A0A1, A1A2, A2A3, A3A4, A4A0 = (1, 0, 0), (a, 1, 0), (b, c, 1), (d, e, 1), (f, g, 1)
    A0, A1, A2, A3, A4 = cross(A4A0, A0A1), cross(A0A1, A1A2), cross(A1A2, A2A3), cross(A2A3, A3A4), cross(A3A4, A4A0)
    B0, B1, B2, B3, B4 = cross(A1A2, A3A4), cross(A2A3, A4A0), cross(A3A4, A0A1), cross(A4A0, A1A2), cross(A0A1, A2A3)
    A2B0A3, A3B1A4, A4B2A0, A0B3A1, A1B4A2 = circle(A2, B0, A3), circle(A3, B1, A4), circle(A4, B2, A0), circle(A0, B3, A1), circle(A1, B4, A2)
    print('A2B0A3:', circle_eq(A2B0A3))
    print('A3B1A4:', circle_eq(A3B1A4))
    print('A4B2A0:', circle_eq(A4B2A0))
    print('A0B3A1:', circle_eq(A0B3A1))
    print('A1B4A2:', circle_eq(A1B4A2))
    C4 = intersect(A3B1A4, A4B2A0, A4)
    print('C4:', C4, flush = True)
    C0 = intersect(A4B2A0, A0B3A1, A0)
    print('C0:', C0, flush = True)
    C1 = intersect(A0B3A1, A1B4A2, A1)
    print('C1:', C1, flush = True)
    C2 = intersect(A1B4A2, A2B0A3, A2)
    print('C2:', C2, flush = True)
    # C0C1C2 = circle(C0, C1, C2)
    # print('C0C1C2:', circle_eq(C0C1C2), flush = True)
    # print('Is C4 on C0C1C2?', on_circle(C0C1C2, C4), flush = True)

if __name__ == '__main__':
    main()


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

#read data
#feature data
dataX=np.genfromtxt("x.csv",delimiter=',')
#target data
dataT=np.genfromtxt("t.csv",delimiter=',')
dataT=dataT.reshape(len(dataT),1)

def normalization(X):
    M=3
    s=0.1
    x_1=(X-(2*0/M))/s
    x_2=(X-(2*1/M))/s
    x_3=(X-(2*2/M))/s
    return np.column_stack((x_1,x_2,x_3))

def sigmoidal(X):
    return 1/(1+np.exp(-1*X))

def bayesian_regression(X,T):
    beta=1
    S_0_inv=np.eye(3)*(10**-6)
    m_0=np.zeros((3,1))
    S_N_inv=S_0_inv+beta*(X.T@X)
    S_N=np.linalg.inv(S_N_inv)
    temp=(S_0_inv@m_0)
    m_N=(S_N@((S_0_inv@m_0)+beta*((X.T@T))))
    return m_N,S_N

N=80
dataX_nor=normalization(dataX[0:N])
dataX_s=sigmoidal(dataX_nor)
m_N,S_N=bayesian_regression(dataX_s,dataT[0:N])

#generate 5 sample curves
#the testing dataset need to pass same data preprocessing
x1=np.linspace(0,2,10000)
x1_nor=normalization(x1)
x1_s=sigmoidal(x1_nor)
weight=np.random.multivariate_normal(m_N.reshape(3,),S_N).reshape(3,1)
y1=x1_s@weight

x2=np.linspace(0,2,10000)
x2_nor=normalization(x2)
x2_s=sigmoidal(x2_nor)
weight=np.random.multivariate_normal(m_N.reshape(3,),S_N).reshape(3,1)
y2=x2_s@weight

x3=np.linspace(0,2,10000)
x3_nor=normalization(x3)
x3_s=sigmoidal(x3_nor)
weight=np.random.multivariate_normal(m_N.reshape(3,),S_N).reshape(3,1)
y3=x3_s@weight

x4=np.linspace(0,2,10000)
x4_nor=normalization(x4)
x4_s=sigmoidal(x4_nor)
weight=np.random.multivariate_normal(m_N.reshape(3,),S_N).reshape(3,1)
y4=x4_s@weight

x5=np.linspace(0,2,10000)
x5_nor=normalization(x5)
x5_s=sigmoidal(x5_nor)
weight=np.random.multivariate_normal(m_N.reshape(3,),S_N).reshape(3,1)
y5=x5_s@weight

#visualize
plt.plot(dataX[0:N],dataT[0:N],'bo',label='training data')
plt.plot(x1,y1,label='sample curve 1')
plt.plot(x2,y2,label='sample curve 2')
plt.plot(x3,y3,label='sample curve 3')
plt.plot(x4,y4,label='sample curve 4')
plt.plot(x5,y5,label='sample curve 5')
plt.xlabel('x')
plt.ylabel('t')
plt.title('training data size: %d'%(N))
plt.legend()
plt.show()

#mean and std calculation
sample_mean=[]
sample_std=[]
hbound=[]
lbound=[]
for i in range(len(y1)):
    sample_mean.append(np.mean([y1[i],y2[i],y3[i],y4[i],y5[i]]))
    sample_std.append(np.std([y1[i],y2[i],y3[i],y4[i],y5[i]]))
    hbound.append(sample_mean[i]+sample_std[i])
    lbound.append(sample_mean[i]-sample_std[i])

#visualize
plt.plot(dataX[0:N],dataT[0:N],'bo',label='training data')
plt.plot(x1,sample_mean,label='mean curve')
plt.fill_between(x1,sample_mean,hbound,facecolor='pink')
plt.fill_between(x1,sample_mean,lbound,facecolor='pink')
plt.xlabel('x')
plt.ylabel('t')
plt.title('training data size: %d'%(N))
plt.legend()
plt.show()

#sample weight calculation and scatter
weight0=[]
weight1=[]
weight2=[]
for i in range(10000):
    weight=np.random.multivariate_normal(m_N.reshape(3,),S_N).reshape(3,1)
    weight0.append(weight[0])
    weight1.append(weight[1])
    weight2.append(weight[2])
weight0 = np.array(weight0).reshape(10000,)
weight1 = np.array(weight1).reshape(10000,)
weight2 = np.array(weight2).reshape(10000,)
plt.hist2d(np.array(weight0),np.array(weight1),range=[[0,5],[-6,6]],bins = 50,cmap = 'rainbow')
plt.xlabel("w[0]")
plt.ylabel("w[1]")
plt.title('weight scatter with training data size: %d' %(N))
plt.colorbar()
plt.show()


import numpy as np
from scipy import stats
import matplotlib.pyplot as plt
plt.rcParams["figure.figsize"] = (15,4)

mu_true = np.array([0.5, 0.5])
sigma_true = 0.1*np.array([[2,1],[1,1]])
n_sample = 10
x_sample = stats.multivariate_normal.rvs(mu_true, sigma_true, n_sample)

# 绘制采样数据和真实数据
ax1 = plt.subplot(131)
ax1.plot(x_sample[:,0], x_sample[:,1], 'bo', markersize=8)
plt.title('data')
ax1.plot(mu_true[0], mu_true[1], marker='x', color='black', markersize=15)
ax1.set_xlim([-1,1])
ax1.set_ylim([-1,1])

# 绘制先验分布
ax2 = plt.subplot(132)
prior_mu = np.array([0,0])
prior_sigma = 0.1*np.eye(2)

xy_range = np.linspace(-1,1,100)
X,Y=np.meshgrid(xy_range, xy_range)
XY = np.dstack((X, Y)).reshape((-1, 2))
Z = stats.multivariate_normal.pdf(XY, prior_mu, prior_sigma).reshape(X.shape)
ax2.contour(X, Y, Z)
plt.title('prior')
ax2.set_xlim([-1,1])
ax2.set_ylim([-1,1])

# 更新协方差矩阵
s_0 = prior_sigma
s0_inv = np.linalg.inv(s_0)
s = sigma_true
s_inv = np.linalg.inv(s)
s_n = np.linalg.inv(s0_inv + n_sample*s_inv)

# 更新期望
mu_0 = prior_mu
x_bar = np.mean(x_sample, 0)[:, np.newaxis]
mu_n = np.dot(s_n, n_sample*s_inv.dot(x_bar) + s0_inv.dot(mu_0[:, np.newaxis]))

# 绘制后验分布
post_mu = mu_n.flatten()
post_sigma = s_n
ax3 = plt.subplot(133)
post_z = stats.multivariate_normal.pdf(XY, post_mu, post_sigma).reshape(X.shape)
ax3.contour(X, Y, post_z)
plt.title('post after 10 obs')
ax3.set_xlim([-1,1])
ax3.set_ylim([-1,1])

plt.show()


# (c) 2019 Francis Taylor
# This code is licensed under the MIT license (see LICENSE for details)
# This code is provided as a guide for learning. Please do not copy it blindly.

# m =  [N Σ(xy) − Σx Σy] / [N Σ(x2) − (Σx)2]
# b = [Σy − m Σx ]/ N
# D:\Coding\git\physics-projects\Projects\Least Sqaures\files\LinearTestData.txt

import numpy as np
from numpy import genfromtxt
import pylab as plt
import os

# todo add errors

file_path = input("Enter the path of your file: ")
file_path = file_path.replace('"', '')
if os.path.isfile(file_path):
    values = genfromtxt(file_path, delimiter='\t', dtype=None)
    # print(values)
    x_vals = values[:, 0]
    x_error = values[:, 2]
    y_vals = values[:, 1]
    y_error = values[:, 3]
    A = np.vstack([x_vals, np.ones(len(x_vals))]).T
    m, c = np.linalg.lstsq(A, y_vals, rcond=None)[0]
    print("y={}x + {}".format(m, c))
    plt.plot(x_vals, y_vals, 'o', label='Original data', markersize=3)
    plt.plot(x_vals, m*x_vals + c, 'r', label='Fitted line')
    plt.legend()
    plt.title("y={:f}x + {:f}".format(m, c))
    plt.show()
else:
    print("File does not exist at: {}".format(str(file_path)))


from __future__ import absolute_import, division, print_function
from functools import reduce
from concurrent import futures
import numpy as np
import scipy.signal as spsg
import rasterio
import click
import os

def horn_gradient(dem):
    x_kernel = np.array([
        [-1/8, 0, 1/8],
        [-1/4, 0, 1/4],
        [-1/8, 0, 1/8]])
    y_kernel = np.array([
        [-1/8, -1/4, -1/8],
        [0, 0, 0],
        [1/8, 1/4, 1/8]])
    dx = spsg.convolve2d(dem, x_kernel)
    dy = spsg.convolve2d(dem, y_kernel)
    return dx, dy

def slope(dem):
    dx, dy = horn_gradient(dem)
    dem_slope = np.arctan(np.sqrt(np.square(dx) + np.square(dy)))
    return dem_slope

def aspect(dem):
    dx, dy = horn_gradient(dem)
    direction = np.arctan2(dy, -dx)
    dem_aspect = np.where(direction > np.pi/2, np.pi*5/2 - direction, np.pi/2 - direction)
    return dem_aspect

def hillshade(dem, azimuth, altitude):
    azimuth_rad = np.deg2rad(azimuth)
    altitude_rad = np.deg2rad(altitude)
    dem_slope = slope(dem)
    dem_aspect = aspect(dem)
    dem_hillshade = 255 * (np.cos(np.pi/2 - altitude_rad) * np.cos(dem_slope) + np.sin(np.pi/2 - altitude_rad) * np.sin(dem_slope) * np.cos(azimuth_rad - dem_aspect))
    return dem_hillshade

def mdow_hillshade(dem, azimuth, altitude):
    azimuth_rad = np.deg2rad(azimuth)
    altitude_rad = np.deg2rad(altitude)
    init_slope = slope(dem)
    init_aspect = aspect(dem)
    init_hillshade = hillshade(dem, azimuth, altitude)
    secondary_azimuths = [np.deg2rad(180+90*(n+1)) for n in range(4)]
    workers = futures.ThreadPoolExecutor(max_workers=os.cpu_count())
    hs_task = lambda az: hillshade(dem, az, altitude)
    w_var_task = lambda az: (np.cos(init_aspect - az) + 1)
    weight_task = lambda w: (w / np.sqrt(2 * w_total))
    secondary_hillshades = list(workers.map(hs_task, secondary_azimuths))
    secondary_w_vars = list(workers.map(w_var_task, secondary_azimuths))
    w_total = reduce(lambda x, y: x + y, secondary_w_vars)
    secondary_weights = list(workers.map(weight_task, secondary_w_vars))
    md_hillshade = reduce(lambda x, y: x + y, [m * n for m, n in zip(secondary_hillshades, secondary_weights)])
    merge_weight = np.square(np.sin(np.sin(altitude_rad) * np.cos(init_slope) + np.sin(init_slope) * np.cos(altitude_rad) * np.cos(init_aspect - azimuth_rad)))
    hs_final = merge_weight * md_hillshade + (1 - merge_weight) * init_hillshade
    mdow = np.min(init_hillshade) + (hs_final - np.min(hs_final)) / (np.max(hs_final) - np.min(hs_final)) * (np.max(init_hillshade) - np.min(init_hillshade))
    return mdow

def read_dem(dem_file):
    src = rasterio.open(dem_file)
    band = src.read(1)
    meta = {
        'height': band.shape[0],
        'width': band.shape[1],
        'count': src.count,
        'dtype': band.dtype,
        'crs': src.crs,
        'transform': src.transform,
        'nodata': src.nodata
    }
    src.close()
    return band, meta

def write_hillshade(file_path, hs, metadata):
    with rasterio.open(file_path, 'w', driver='GTiff', height=metadata['height'], width=metadata['width'], count=metadata['count'], dtype=metadata['dtype'], crs=metadata['crs'], transform=metadata['transform'], nodata=metadata['nodata']) as dst:
        dst.write(hs.astype(metadata['dtype']), 1)

def run(in_path, out_path, azimuth, altitude):
    arr, meta = read_dem(in_path)
    md = mdow_hillshade(arr, azimuth, altitude)
    write_hillshade(out_path, md, meta)

def validate_azimuth(ctx, param, value):
    if 0 <= value <= 360:
        return value
    else:
        raise click.BadParameter('Azimuth should be between 0 and 360.')

def validate_altitude(ctx, param, value):
    if 0 <= value <= 90:
        return value
    else:
        raise click.BadParameter('Altitude should be between 0 and 90.')

@click.command()
@click.option('-i', '--in', 'in_path', help='Input DEM path.', required=True, type=str)
@click.option('-o', '--out', 'out_path', help='Output hillshade path.', required=True, type=str)
@click.option('--azimuth', 'azimuth', help='Hillshade azimuth in degree.', required=True, type=float, callback=validate_azimuth)
@click.option('--altitude', 'altitude', help='Hillshade altitude in degree.', required=True, type=float, callback=validate_altitude)
def cmd(in_path, out_path, azimuth, altitude):
    """MDOW Hillshade Generator."""
    run(in_path, out_path, azimuth, altitude)

if __name__ == '__main__':
    cmd()


import numpy as np

def sigmoid(x):
    """
    S(x) = 1 / ( 1 + e^(-x) )
    :param x: input
    :return: S(x)
    """
    return 1 / (1 + np.exp(-x))

def relu(x):
    """
    f(x) = max(0, x)
    :param x:
    :return:
    """
    return max(0, x)

def tanh(x):
    """
    tanh x = (sinh x)/(cosh x) = (e^x - e(-x)) / (e^x + e(-x))
    :param x:
    :return:
    """
    return (np.exp(x) - np.exp(-x)) / (np.exp(x) + np.exp(-x))

def softmax(inputs):
    """
    y_k = exp(x_k) / sum(exp(x_i))
    :param inputs:
    :return:
    """
    _max = np.max(inputs)
    _exp = np.exp(inputs - _max)  # avoid overflow
    _sum_exp = np.sum(_exp)
    return _exp / _sum_exp


# T-Test Assignment

import numpy as np

"""
1.Certain refined edible oil is packed in tins holding 16 kg each. The filling machine can maintain this but with a standard deviation of 0.5 kg. Samples of 25 are taken from the production line. If a sample means is (i)16.35kg (ii)15.8kg, Can we be 95 percent sure that the sample has come from a population of 16kg tins?
"""

print("Assignment 1")

from scipy.stats import t
print("\nTrial 1 with 16.35")
pMean=16
sMean=16.35
n=25
tstatistics=(sMean-pMean)/(0.5/np.sqrt(n))
print("T Statistics:",tstatistics)
tcritical_l=t.ppf(q=0.05/2,df=n-1)
tcritical_u=-tcritical_l

if tstatistics<tcritical_l or tstatistics>tcritical_u:
    print("Reject the Null Hypothesis")
else:
    print("Fail to reject the Null Hypothesis")

print("\nTrial 2 with 15.8")
pMean=16
sMean=15.8
n=25
tstatistics=(sMean-pMean)/(0.5/np.sqrt(n))
print("T Statistics:",tstatistics)
tcritical_l=t.ppf(q=0.05/2,df=n-1)
tcritical_u=-tcritical_l

if tstatistics<tcritical_l or tstatistics>tcritical_u:
    print("Reject the Null Hypothesis")
else:
    print("Fail to reject the Null Hypothesis")

print("\n")

"""
2.A filling machine is expected to fill 5kg of powder into bags. A sample of 10 bags gave the weighs 4.7, 4.9, 5.0, 5.1, 5.4, 5.2, 4.6,5.1, 4.6 and 4.7. Test whether the machine is working properly.
"""
print("Assignment 2")
from scipy.stats import ttest_1samp
sample_array=np.array([4.7, 4.9, 5.0, 5.1, 5.4, 5.2, 4.6,5.1, 4.6, 4.7])
tstats,pvalue=ttest_1samp(sample_array,5)

print("T-statistics:",tstats)
print("P value:",pvalue)

if pvalue < 0.05:
    print("Reject the Null Hypothesis")
    print("The filling machine is working properly")
else:
    print("Fails to reject the Null Hypothesis")
    print("The filling machine is working properly")
print("\n")

"""
3.Two sets of ten students selected at random from a college were taken; One set was given memory test as they were and the other was given the memory test after two weeks of training and the scores are given below
Set A: 10 8 7 9 8 10 9 6 7 8
Set B: 12 8 8 10 8 11 9 8 9 9
Do you think there is a significant effect due to training?
"""
print("Assignement 3")

sample1=np.array([10,8,7,9,8,10,9,6,7,8])
sample2=np.array([12,8,8,10,8,11,9,8,9,9])

from scipy.stats import ttest_ind

tstats,pvalue=ttest_ind(sample1,sample2)

print("T-statistics:",tstats)
print("P value:",pvalue)

if pvalue < 0.05:
    print("Reject the Null Hypothesis")
    print("No significant effect due to Training")
else:
    print("Fails to reject the Null Hypothesis")
    print("Significant effect due to Training")


##%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
##                          PCA model for TE data
## %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

#%% import required packages
import numpy as np
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt

#%% fetch TE data
TEdata_noFault_train = np.loadtxt('d00.dat').T

# select data as done in Lee et al.
xmeas = TEdata_noFault_train[:,0:22]
xmv = TEdata_noFault_train[:,41:52]
data_noFault_train = np.hstack((xmeas, xmv))

#%% scale data
scaler = StandardScaler()
data_train_normal = scaler.fit_transform(data_noFault_train)

#%% decide # of PCs to retain via PCA variance method
pca = PCA().fit(data_train_normal)

explained_variance = 100*pca.explained_variance_ratio_
cum_explained_variance = np.cumsum(explained_variance)

n_comp = np.argmax(cum_explained_variance >= 90) + 1

#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
##                     Monitoring statistics function
## %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

def compute_PCA_monitoring_metrics(pca_model, number_comp, data):
    """ calculate monitoring statistics for given data

    parameters
    -----------
    data: numpy array of shape = [n_samples, n_features]
          Training or test data

    Returns
    ----------
    monitoring_stats: numpy array of shape = [n_samples, 2]

    """

    # data parameters
    n = data.shape[0]

    # model parameters
    V_matrix = pca.components_.T
    P_matrix = V_matrix[:,0:n_comp]

    # model computation
    score = pca.transform(data)
    score_reduced = score[:,0:n_comp]
    data_reconstruct = np.dot(score_reduced, P_matrix.T)

    # T2
    lambda_k = np.diag(pca.explained_variance_[0:n_comp])
    lambda_k_inv = np.linalg.inv(lambda_k)
    T2 = np.zeros((data.shape[0],))
    for i in range(n):
        T2[i] = np.dot(np.dot(score_reduced[i,:],lambda_k_inv),score_reduced[i,:].T)

    # SPE
    error = data - data_reconstruct
    SPE = np.sum(error*error, axis = 1)

    monitoring_stats = np.column_stack((T2, SPE))
    return monitoring_stats

def draw_monitoring_chart(values, CL, yLabel):
    plt.figure()
    plt.plot(values)
    plt.axhline(CL, color = "red", linestyle = "--")
    plt.xlabel('Sample #')
    plt.ylabel(yLabel)
    plt.show()

def draw_PCA_monitoring_charts(PCA_statistics, CLs, trainORtest):
    """ draw monitoring charts for given data

    parameters
    -----------
    PCA_statistics: numpy array of shape = [n_samples, 2]
    CLs: List of control limits
    trainORtest: 'training' or 'test'

    """

    # T2 chart, SPE chart
    draw_monitoring_chart(PCA_statistics[:,0], CLs[0], 'T2 for ' + trainORtest + ' data')
    draw_monitoring_chart(PCA_statistics[:,1], CLs[1], 'SPE for ' + trainORtest + ' data')

#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
##                   Draw monitoring charts for training data
## %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
PCA_statistics_train = compute_PCA_monitoring_metrics(pca, n_comp, data_train_normal)

T2_CL = np.percentile(PCA_statistics_train[:,0], 99)
SPE_CL = np.percentile(PCA_statistics_train[:,1], 99)

draw_PCA_monitoring_charts(PCA_statistics_train, [T2_CL, SPE_CL], 'training')

#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
##                   FAR / FDR computation function
## %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
def compute_alarmRate(monitoring_stats, CLs):
    """ calculate false rate

    parameters
    -----------
    monitoring_stats: numpy array of shape = [n_samples, 2]
    CLs: List of control limits

    Returns
    ----------
    alarmRate: float

    """

    violationFlag = monitoring_stats > CLs
    alarm_overall = np.any(violationFlag, axis=1) # violation of any metric => alarm
    alarmRate = 100*np.sum(alarm_overall)/monitoring_stats.shape[0]

    return alarmRate

#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
##                   Draw monitoring charts for test data
## %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
# fetch data
TEdata_Fault_test = np.loadtxt('d05_te.dat')

# select data as done in Lee et al.
xmeas = TEdata_Fault_test[:,0:22]
xmv = TEdata_Fault_test[:,41:52]
data_Fault_test = np.hstack((xmeas, xmv))

# scale data
data_test_scaled = scaler.transform(data_Fault_test)

# compute statistics and draw charts
PCA_statistics_test = compute_PCA_monitoring_metrics(pca, n_comp, data_test_scaled)
draw_PCA_monitoring_charts(PCA_statistics_test, [T2_CL, SPE_CL], 'test')

# compute FAR or FDR
alarmRate = compute_alarmRate(PCA_statistics_test[160:,:], [T2_CL, SPE_CL]) # faults start from sample 160
print(alarmRate)


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

import numpy as np
from sympy import *
from math import *

from timeit import default_timer as timer

def phix(a, b, c, x0,x): # define função phi(x)

    return a - (b.subs(x,x0)/c.subs(x,x0))

def xProximo(y,Y):

    xR = Y[0,0]

    for i in range(1,Y.shape[1]):

        if(abs(Y[0,i] - y) < abs(xR - y)):
            xR = Y[0,i]
    return xR

def newtonRaphson(fx,dfx,x0,e,c,x):

    phi = None
    d = 0

    while (d < c) :

        phi = phix(x0,fx,dfx,x0,x) # calcula phi(x0)

        if(abs(fx.subs(x,x0)) < e): # checa se a função em x0 é menor ou igual à precisão desejada

            return [phi,0,d]

        x0 = phi # caso f(x) não seja perto de 0 o suficiente, x0 recebe o valor de phi(x0) e segue no laço

        if(d == c-1):

            return [phi,1]

        d+=1

def diferencasDivididas(X,Y):
    if(Y.shape[1] == 1):

        return Y[0]

    else:

        X1 = X[:,1:]
        X0 = X[:,:(X.shape[1]-1)]
        Y1 = Y[:,1:]
        Y0 = Y[:,:(Y.shape[1]-1)]

        d = (diferencasDivididas(X1,Y1) - diferencasDivididas(X0,Y0))/(X[X.shape[1]-1] - X[0])

        return d

start = None
end = None

x = symbols('x')

X = Matrix(eval(input("\n\n   Digite o vetor x: ")))
Y = Matrix(eval(input("   Digite o vetor y: ")))

Xp = ones(X.shape[0],X.shape[1])*x - X[:,:]

Pn = zeros(X.shape[0],X.shape[1])

Pn[0,0] = Y[0,0]

Sn = Y[0,0]

start = timer()

for i in range(1,X.shape[1]):

    p = 1

    for j in range(0,i):

        p *= Xp[0,j]

    Pn[0,i] = p*diferencasDivididas(X[:,:(i+1)],Y[:,:(i+1)])

end = timer()

for i in range(1,Pn.shape[1]):

    Sn += Pn[0,i]

Sn = sympify(Sn)
c = 30
y0 = float(input("   Digite um valor de y para ser testado no polinômio interpolado: "))
e = float(input("   Digite a precisão do x estimado: "))
Sn2 = Sn - y0
print("   Pn(x) = "+str(Sn))
print("   f(xk) = "+str(y0))
print("   xk = "+str(newtonRaphson(Sn2,diff(Sn2,x),xProximo(y0,Y),e,c,x)[0]))
print("   Tempo de execucao total: %e segundos\n\n" % (end - start))


import numpy as np
from numpy import linalg as la

def r_squared(x, y):
    """
    Fit a linear regression to :math:`y` and return the :math:`R^2` statistical measure of a fit of a linear regression

    Args:
        x (``np.ndarray``): The :math:`x` coordinates of the points
        y (``np.ndarray``): The :math:`y` coordinates of the points

    Returns:
         ``float``: The :math:`R^2` measure of a fit. Bounded by :math:`\\left[0, 1\\right]`. The closer :math:`R^2` is
         to :math:`1`, the better the fit.

    """
    x = x.ravel()
    y = y.ravel()
    assert x.ndim == y.ndim
    assert len(x) == len(y)
    n = len(x)
    xx = np.stack((np.ones(n), x))
    w, ssr, _, _ = la.lstsq(xx.T, y, rcond=None)
    if ssr.size == 0:
        ssr = 0
    sst = np.var(y, ddof=n - 1)
    r2_1 = (1 - ssr / sst).item()
    corr = np.corrcoef(w @ xx, y)[0, 1]
    r2_2 = corr**2
    assert np.allclose(r2_1, r2_2)
    return ((r2_1 + r2_2) / 2).item()

def ols_swiping(x, y, **kwargs):
    """
    Performs OLS swiping method.

    By first selecting a pivot point, all the data points are implicitly split into two parts: the left one and the
    right one. Then, the algorithm regresses a line onto :math:`y` with respect to :math:`x` for both parts using
    ordinary least squares. If both lines fit quite well, meaning the :math:`R^2` for both left and the right fit is
    particularly high, the pivot point is declared as a knee.

    Args:
        x (``np.ndarray``): the :math:`x` coordinates of the points
        y (``np.ndarray``): the :math:`y` coordinates of the points
        **kwargs: possible additional arguments (none are used)

    Returns:
        ``int``: the index of the knee
    """
    assert len(kwargs) == 0
    n = len(x)
    # some python magic
    # generator of all the splits, linear regressions and the sums of particular r2 coefficients
    results = ((i, r_squared(x[: i + 1], y[: i + 1]) + r_squared(x[i:], y[i:])) for i in range(1, n - 1))
    # the values are only calculated as the generator is consumed :))
    return min(results, key=lambda t: t[1])[0]


import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
from scipy.stats import binom
from scipy import linalg
from scipy.sparse.linalg import expm_multiply
from scipy.sparse import csc_matrix
from scipy.special import comb
import math
import time

def hypercube(n_dim):
    n = n_dim - 1
    sigma_x = np.array([[0, 1],
                        [1, 0]])
    A = sigma_i(sigma_x, 0, n)

    for i in range(1, n_dim):
        A += sigma_i(sigma_x, i, n)
    return -1 * A

def sigma_i(sigma_x, i, n):
    if i > 0:
        out = np.eye(2)
        for j_before in range(i - 1):
            out = np.kron(out, np.eye(2))
        out = np.kron(out, sigma_x)
    else:
        out = sigma_x
    for j_after in range(n - i):
        out = np.kron(out, np.eye(2))
    return out

def quantum_walk_hypercube(N, H, psi0, timesteps, normalise):
    psiN = expm_multiply(-(1j) * timesteps * H, psi0)

    prob = np.real(np.conj(psiN) * psiN)

    result = np.zeros(N + 1)
    normalise_array = np.zeros(N+1)

    for i, probability in enumerate(prob):
        binary_i = bin(i)
        i_ones = [ones for ones in binary_i[2:] if ones == '1']
        num_ones = len(i_ones)
        result[num_ones] += probability
        if normalise:
            normalise_array[num_ones] += 1

    if normalise:
        result = result/normalise_array

    return result

def run_many_walks(n, time_limit, gamma, normalise=False):
    P = 2 ** n  # number of positions
    A = hypercube(n)
    marked_state = np.zeros((2 ** n, 2 ** n))
    marked_state[0, 0] = 1
    H = gamma * (A - n * np.eye(2 ** n)) - marked_state  # not sure if marked_node should also be multiplied by gamma

    psi0 = np.ones(P) * (1 / np.sqrt(2 ** n))
    output = np.zeros((time_limit + 1, n + 1))
    for timesteps in range(0, time_limit + 1):
        output[timesteps] = quantum_walk_hypercube(n, H, psi0, timesteps, normalise=normalise)
        print(sum(output[timesteps]))
    return output

def plot_furthest_qubit_prob(timesteps, data):
    plt.figure()
    plt.plot(range(timesteps + 1), data[:, -1])
    plt.xlim(0, timesteps)
    plt.xticks(range(0, timesteps + 1, 5))
    plt.ylim(0, 1)
    plt.yticks([0, 0.2, 0.4, 0.6, 0.8, 1])
    plt.show()

def plot_nearest_qubit_prob(timesteps, data):
    plt.figure()
    plt.plot(range(timesteps + 1), data[:, 0])
    plt.xlim(0, timesteps)
    plt.xticks(range(0, timesteps + 1, 5))
    plt.ylim(0, 1)
    plt.yticks([0, 0.2, 0.4, 0.6, 0.8, 1])
    plt.show()

def plot_prob_heatmap(data, N, timesteps):
    fig, ax = plt.subplots()
    im = ax.imshow(data.T, interpolation="gaussian", cmap=plt.get_cmap('plasma'))
    ax.set_xlabel("Time, t")
    ax.set_ylabel("Hamming distance, d")
    plt.yticks(range(0, N + 1, 2))
    plt.xticks(range(0, timesteps + 1, 5))
    ax.invert_yaxis()

    cb = fig.colorbar(cm.ScalarMappable(cmap=plt.get_cmap('plasma')))
    cb.set_label('Normalised probability, P(d, t)')

    plt.show()

def optimal_gamma(n):
    N = 2**n
    gam = 0
    for r in range(1, n+1):
        gam += comb(n, r) * (1/r)
    gam = (1/2) * (1/N) * gam
    return gam

if __name__ == '__main__':
    time_start = time.time()

    n = 8  # number of dimensions of hypercube
    timesteps = 50
    gamma = optimal_gamma(n)    # hopping rate
    print("gamma:", gamma)

    data = run_many_walks(n, timesteps, gamma, normalise=True)  # 2D array of [timesteps_run, probability_at_distance_of_index]

    time_end = time.time()
    print("runtime:", time_end - time_start)

    #plot_furthest_qubit_prob(timesteps, data)
    plot_nearest_qubit_prob(timesteps, data)
    plot_prob_heatmap(data, n, timesteps)


# -*- coding: utf-8 -*-
"""
@author: Makan Arastuie
"""

import numpy as np
from os.path import join
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from scipy.sparse.linalg import svds
from sklearn.preprocessing import normalize

def spectral_cluster(adj, num_classes=2, n_kmeans_init=10, normalize_z=True, verbose=False, plot_eigenvalues=False,
                     plot_save_path=''):
    """
    Runs spectral clustering on weighted or unweighted adjacency matrix

    :param adj: weighted, unweighted or regularized adjacency matrix
    :param num_classes: number of classes for spectral clustering
    :param n_kmeans_init: number of initializations for k-means
    :param normalize_z: If True, vector z is normalized to sum to 1
    :param verbose: if True, prints the eigenvalues
    :param plot_eigenvalues: if True, plots the first `num_classes` singular values
    :param plot_save_path: directory to save the plot

    :return: predicted clustering membership
    """
    # Compute largest num_classes singular values and vectors of adjacency matrix
    u, s, v = svds(adj, k=num_classes)
    v = v.T

    if verbose:
        print("Eigenvalues: \n", s)

    if plot_eigenvalues:
        fig, ax = plt.subplots()
        plt.scatter(np.arange(num_classes, 0, -1), s, s=80, marker='*', color='blue')
        plt.xlabel('Rank', fontsize=24)
        plt.ylabel('Singular Values', fontsize=24)
        plt.grid(True)
        ax.tick_params(labelsize=20)
        plt.tight_layout()
        plt.savefig(join(plot_save_path, 'singular_values.pdf'))
        plt.show()

    # Sort in decreasing order of magnitude
    sorted_ind = np.argsort(-s)
    u = u[:, sorted_ind]
    v = v[:, sorted_ind]

    z = np.c_[u, v]

    if normalize_z:
        z = normalize(z, norm='l2', axis=1)

    km = KMeans(n_clusters=num_classes, n_init=n_kmeans_init)
    cluster_pred = km.fit_predict(z)

    return cluster_pred

def regularized_spectral_cluster(adj, num_classes=2, tau=None, n_kmeans_init=10, normalize_z=True):
    """
    Runs regularized spectral clustering on weighted or unweighted adjacency matrix

    :param adj: weighted, unweighted or regularized adjacency matrix
    :param num_classes: number of classes for spectral clustering
    :param tau: regularization parameter
    :param n_kmeans_init: number of initializations for k-means
    :param normalize_z: If True, vector z is normalized to sum to 1

    :return: predicted clustering membership
    """
    node_outdegree = np.sum(adj, axis=1)
    node_indegree = np.sum(adj, axis=0)

    if tau is None:
        tau = np.mean(node_outdegree)

    o_t = np.diag(1 / np.sqrt(node_outdegree + tau))
    p_t = np.diag(1 / np.sqrt(node_indegree + tau))
    l_t = o_t.dot(adj).dot(p_t)

    return spectral_cluster(l_t, num_classes, n_kmeans_init, normalize_z)


import matplotlib.pyplot as plt
import numpy as np

# 根据均值、标准差,求指定范围的正态分布概率值
def norm_fun(x, mu, sigma):
    pdf = np.exp(-((x - mu) ** 2) / (2 * sigma ** 2)) / (sigma * np.sqrt(2 * np.pi))
    return pdf

if __name__ == '__main__':
    # result = np.random.randint(-65, 80, size=100) # 最小值,最大值,数量
    result = np.random.normal(15, 44, 100)  # 均值为0.5,方差为1
    print(result)
    x = np.arange(min(result), max(result), 0.1)
    # 设定 y 轴，载入刚才的正态分布函数
    print(result.mean(), result.std())
    y = norm_fun(x, result.mean(), result.std())
    plt.plot(x, y)  # 这里画出理论的正态分布概率曲线
    # 这里画出实际的参数概率与取值关系
    plt.hist(result, bins=10, rwidth=0.8, density=True)  # bins个柱状图,宽度是rwidth(0~1),=1没有缝隙
    plt.title('distribution')
    plt.xlabel('temperature')
    plt.ylabel('probability')
    # 输出
    plt.show()  # 最后图片的概率和不为1是因为正态分布是从负无穷到正无穷,这里指截取了数据最小值到最大值的分布


#
# main.py
#

import os
import math
import implementation
import numpy as np
import scipy.constants
import matplotlib.pyplot as plot

frequency  = 300*math.pow(10, 6)
wavelength = float(scipy.constants.c)/frequency

'''
Plot the current distribution of a half-wavelength dipole antenna
along the z axis using 3, 7 and 19 triangular base functions. Also,
print the input impedance of the configurations.
'''

plots = []
impedances = []

segments_count = [3, 7, 19]
antenna_length = wavelength*(0.5)
antenna_radius = wavelength*math.pow(10, -4)

for count in segments_count:

    powered_segment = (count//2)+1
    half_base_width = float(antenna_length)/(count+1)

    I = implementation.solve_dipole_antenna_mom(
        frequency=frequency,
        antenna_length=antenna_length,
        antenna_radius=antenna_radius,
        segments_count=count,
        powered_segment=powered_segment
    )

    I_in = I[powered_segment-1]
    Z_in = 1/I_in

    I_absolute = np.absolute(I)
    I_mV = [(i*1000) for i in I_absolute]
    I_mV = [0] + I_mV + [0]

    x_neg = [ ( ((n*half_base_width)-(antenna_length/2)) / wavelength)  for n in range((count+2)//2)]
    x_pos = [-x for x in x_neg]
    x_rev = [x for x in reversed(x_pos)]
    x = x_neg + [0] + x_rev

    plots.append([x, I_mV])
    impedances.append(Z_in)

plot.figure()
plot.plot(plots[0][0], plots[0][1], "g-+")
plot.plot(plots[1][0], plots[1][1], "b-x")
plot.plot(plots[2][0], plots[2][1], "r-")
plot.legend(["N=3", "N=7", "N=19"], loc="upper right")
plot.title("Current Distribution (L = λ/2)")
plot.xlabel("Z/λ")
plot.ylabel("|I| (mA)")
plot.savefig("graphs/half-wavelength-currents.pdf", bbox_inches="tight")

print("")
print("Half-wavelength dipole antenna input impedance:")
for i in range(len(segments_count)):
    print(format(segments_count[i], '02d') + " " + str(impedances[i]))

'''
Plot the inpute impedance active and reactive components for a
half-wavelength dipole antenna using 3..49 triangular base functions.
'''

actives = []
reactives = []

segments_count = [x for x in range(3, 50) if (x%2) != 0]
antenna_length = wavelength*(0.5)
antenna_radius = wavelength*math.pow(10, -4)

for count in segments_count:

    powered_segment = (count//2)+1
    half_base_width = float(antenna_length)/(count+1)

    I = implementation.solve_dipole_antenna_mom(
        frequency=frequency,
        antenna_length=antenna_length,
        antenna_radius=antenna_radius,
        segments_count=count,
        powered_segment=powered_segment
    )

    I_in = I[powered_segment-1]
    Z_in = 1/I_in

    actives.append([count, Z_in.real])
    reactives.append([count, Z_in.imag])

plot.figure()
plot.plot([x[0] for x in actives], [x[1] for x in actives], "g-")
plot.plot([x[0] for x in reactives], [x[1] for x in reactives], "b-")
plot.legend(["R (Ω)", "X (Ω)"], loc="center right")
plot.title("Input Impedance (L = λ/2)")
plot.xlabel("Z/λ")
plot.savefig("graphs/half-wavelength-impedances.pdf", bbox_inches="tight")

'''
Plot the current distribution of a wavelength dipole antenna along
the z axis using 3, 7 and 19 triangular base functions. Also, print
the input impedance of the configurations.
'''

plots = []
impedances = []

segments_count = [3, 7, 19]
antenna_length = wavelength
antenna_radius = wavelength*math.pow(10, -4)

for count in segments_count:

    powered_segment = (count//2)+1
    half_base_width = float(antenna_length)/(count+1)

    I = implementation.solve_dipole_antenna_mom(
        frequency=frequency,
        antenna_length=antenna_length,
        antenna_radius=antenna_radius,
        segments_count=count,
        powered_segment=powered_segment
    )

    I_in = I[powered_segment-1]
    Z_in = 1/I_in

    I_absolute = np.absolute(I)
    I_mV = [(i*1000) for i in I_absolute]
    I_mV = [0] + I_mV + [0]

    x_neg = [ ( ((n*half_base_width)-(antenna_length/2)) / wavelength)  for n in range((count+2)//2)]
    x_pos = [-x for x in x_neg]
    x_rev = [x for x in reversed(x_pos)]
    x = x_neg + [0] + x_rev

    plots.append([x, I_mV])
    impedances.append(Z_in)

plot.figure()
plot.plot(plots[0][0], plots[0][1], "g-+")
plot.plot(plots[1][0], plots[1][1], "b-x")
plot.plot(plots[2][0], plots[2][1], "r-")
plot.legend(["N=3", "N=7", "N=19"], loc="upper right")
plot.title("Current Distribution (L = λ)")
plot.xlabel("Z/λ")
plot.ylabel("|I| (mA)")
plot.savefig("graphs/wavelength-currents.pdf", bbox_inches="tight")

print("")
print("Wavelength dipole antenna input impedance:")
for i in range(len(segments_count)):
    print(format(segments_count[i], '02d') + " " + str(impedances[i]))
print("")

'''
Plot the inpute impedance active and reactive components for a
wavelength dipole antenna using 3..49 triangular base functions.
'''

actives = []
reactives = []

segments_count = [x for x in range(3, 50) if (x%2) != 0]
antenna_length = wavelength
antenna_radius = wavelength*math.pow(10, -4)

for count in segments_count:

    powered_segment = (count//2)+1
    half_base_width = float(antenna_length)/(count+1)

    I = implementation.solve_dipole_antenna_mom(
        frequency=frequency,
        antenna_length=antenna_length,
        antenna_radius=antenna_radius,
        segments_count=count,
        powered_segment=powered_segment
    )

    I_in = I[powered_segment-1]
    Z_in = 1/I_in

    actives.append([count, Z_in.real])
    reactives.append([count, Z_in.imag])

plot.figure()
plot.plot([x[0] for x in actives], [x[1] for x in actives], "g-")
plot.plot([x[0] for x in reactives], [x[1] for x in reactives], "b-")
plot.legend(["R (Ω)", "X (Ω)"], loc="center right")
plot.title("Input Impedance (L = λ/2)")
plot.xlabel("Z/λ")
plot.savefig("graphs/wavelength-impedances.pdf", bbox_inches="tight")

'''
Delete bytecode files and the cache folder.
'''

os.system("find . -type f -name \"*.pyc\" -delete")
os.system("rm -rf __pycache__")


import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0,4,10001)
y = 0*x
y[np.logical_and(1<x,x<=2)] = x[np.logical_and(1<x,x<=2)]-1
y[np.logical_and(2<x,x<=3)] = 1 - np.sqrt(.3-.25) + np.sqrt(0.3 - (x[np.logical_and(2<x,x<=3)]-2.5)**2)
y[x>3] = 1

fig = plt.figure(figsize=(4, 3))
plt.plot(x,y, linewidth=2.0)
# plt.gca().set_aspect('equal', adjustable='box')
plt.xticks([0,1,2,3,4])
plt.tick_params(labelsize=14, left="off", labelleft="off")
plt.xlabel("time", fontsize=14)
plt.ylabel("distance", fontsize=14)
fig.set_tight_layout(True)
plt.savefig("calcQ.pdf")

fig = plt.figure(figsize=(4, 3))
# plt.plot(x[1:],np.diff(y), linewidth=2.0)
x = x[1:]
dydx = np.diff(y)
d1 = x<1
d2 = np.logical_and(1<x,x<2)
d3 = np.logical_and(2<x,x<3)
d4 = x>3
plt.plot(x[d1],dydx[d1], 'b', linewidth=2.0)
plt.plot(x[d2],dydx[d2], 'b', linewidth=2.0)
plt.plot(x[d3],dydx[d3], 'b', linewidth=2.0)
plt.plot(x[d4],dydx[d4], 'b', linewidth=2.0)

plt.xticks([0,1,2,3,4])
plt.yticks([0])
plt.tick_params(labelsize=14)
plt.xlabel("time", fontsize=14)
plt.ylabel("velocity", fontsize=14)
fig.set_tight_layout(True)
plt.savefig("calcA.pdf")


import numpy as np

def normPDF(x, mean, sigma):
    return exp(-1.*(x-mean)**2/(2.*sigma**2))
    # return (1/np.sqrt(2.*np.pi*sigma**2))*exp(-1.*(x-mean)**2/(2.*sigma**2))

def normSigma(x, mean, probability):
    return np.sqrt(-0.5*(x-mean)**2/np.log(probability))

def normInverse(p, mu, sigma):
    """
    return the offset to the Gaussian center given the Gaussian informaton

    Keyword arguments:
    p -- the Gaussian probabilty
    mu -- the center of the Gaussian
    sigma -- the deviation  of the Gaussian

    return:
    offset -- the offset to the Gaussian center given the parameters

    """

    x = np.sqrt(-2.*sigma**2.*np.log(p))+mu
    return x


import matplotlib.pyplot as plt
import numpy as np

u = np.linspace(-3, 3, 25)
v = np.linspace(-3, 3, 25)
uu, vv = np.meshgrid(u, v)
z = uu + 1j * vv
# w = 1/z
# w = np.exp(z)
# w = np.log(z)
w = np.sin(z)
T = np.arctan2(uu, vv)

fig = plt.figure()
ax = fig.add_subplot(111)
color = 2 * np.log(np.hypot(np.real(w), np.imag(w)))
# ax.streamplot(np.real(z), np.imag(z), np.real(w), np.imag(w), color=color, linewidth=1, cmap=plt.cm.inferno,
#               density=2, arrowstyle='->', arrowsize=1.5)

Q = plt.quiver(np.real(z), np.imag(z), np.real(w), np.imag(w), units='width')
qk = plt.quiverkey(Q, 0.9, 0.9, 2, r'$2 \frac{m}{s}$', labelpos='E',
                   coordinates='figure')

ax.set_xlabel('$x$')
ax.set_ylabel('$y$')
# ax.set_xlim(-2, 2)
# ax.set_ylim(-2, 2)
ax.set_aspect('equal')
# plt.title('f(z)=1/z')
# plt.title('f(z)=exp(z)')
# plt.title('f(z)=log(z)')
plt.title('f(z)=sin(z)')
plt.show()


import math
import copy
import numpy as np

class Complex:

    # No initialization is needed as this is merely a class of functions, as Python already has a fairly robust
    # complex number library that was well worth using, as its basis is in one of the c languages

    # Returns the norm (magnitude) of the complex number - tested in complex_norms_test.py
    @staticmethod
    def norm(c=complex):
        return math.sqrt((c.real ** 2 + c.imag ** 2))

    # Returns the normed (unit) version of the compelx number - tested in complex_norms_test.py
    @staticmethod
    def normed(c=complex):
        norm = Complex.norm(c)
        return complex(c.real / norm, c.imag / norm)

    # Returns the same complex number but with the imaginary component negated - tested in complex_conjugate_test.py
    @staticmethod
    def conjugate(c=complex):
        return complex(c.real, c.imag * -1)

# Two Dimensional Vectors - the mentioned R2 coordinate space.

class Vector2:

    def __init__(self, a, b):
        self.a = a  # value along x axis
        self.b = b  # value alogn y axis

    # Multiplies the vector by a scalar - evaluated in vector2_scale_test.py
    def scale(self, scalar):
        return Vector2(self.a * scalar, self.b * scalar)

    # Returns the norm (magnitude) of the vector - tested in vector2_norms_test.py
    @property
    def norm(self):
        return math.sqrt((self.a ** 2 + self.b ** 2))

    # Returns the normed (unit) version of the vector - tested in vector2_norms_test.py
    @property
    def normed(self):
        norm = self.norm
        return Vector2(self.a / norm, self.b / norm)

    # Prints the vector in <i, j> form
    @property
    def string(self):
        return f'<{self.a}, {self.b}>'

    # Returns the sum of n vectors - tested in vector2_sum_difference_test.py
    @classmethod
    def sum(cls, *args):
        v = copy.copy(args[0])

        for j in args[1:]:
            a = v.a + j.a
            b = v.b + j.b
            v.a, v.b = a, b  # Not too sure why this final line is needed; answer was incorrect otherwise
        return v

    # Returns the difference of n vectors - tested in vector2_sum_difference_test.py
    @classmethod
    def difference(cls, *args):
        v = copy.copy(args[0])

        for j in args[1:]:
            a = v.a - j.a
            b = v.b - j.b
            v.a, v.b = a, b  # Not too sure why this final line is needed; answer was incorrect otherwise
        return v

    # Returns the dot product of two vectors - tested in vector2_dot_test.py
    @classmethod
    def dot_product(cls, v1, v2):
        return v1.a * v2.a + v1.b * v2.b

    # This function determines the angle between two vectors using the dot product of the normed inputs and acos. Output
    # is in radians. - tested in vector2_angle_test.py
    @classmethod
    def angle(cls, v1, v2):
        v1 = v1.normed
        v2 = v2.normed
        dot = cls.dot_product(v1, v2)
        return math.acos(dot)

# Three Dimensional Vectors - the mentioned R3 coordinate space.

class Vector3:

    # Initialization

    def __init__(self, a, b, c):
        self.a = a  # value along x axis
        self.b = b  # value along y axis
        self.c = c  # value along z axis

    # Multiplies the vector by a scalar - evaluated in vector3_scale_test.py
    def scale(self, scalar):
        return Vector3(self.a * scalar, self.b * scalar, self.c * scalar)

    # Properties

    # Returns the norm (magnitude) of the vector - tested in vector3_norms_test.py
    @property
    def norm(self):
        return math.sqrt((self.a ** 2 + self.b ** 2 + self.c ** 2))

    # Returns the normed (unit) version of the vector - tested in vector3_norms_test.py
    @property
    def normed(self):
        return self.scale(scalar=(1 / self.norm))

    # Prints the vector in <i, j, k> form
    @property
    def string(self):
        return f'<{self.a}, {self.b}, {self.c}>'

    # Class Methods

    # Returns the sum of n vectors - tested in vector3_sum_difference_test.py
    @classmethod
    def sum(cls, *args):
        v = copy.copy(args[0])

        for j in args[1:]:
            a = v.a + j.a
            b = v.b + j.b
            c = v.c + j.c
            v.a, v.b, v.c = a, b, c  # Not too sure why this final line is needed; answer was incorrect otherwise
        return v

    # Returns the difference of n vectors - tested in vector3_sum_difference_test.py
    @classmethod
    def difference(cls, *args):
        v = copy.copy(args[0])

        for j in args[1:]:
            a = v.a - j.a
            b = v.b - j.b
            c = v.c - j.c
            v.a, v.b, v.c = a, b, c  # Not too sure why this final line is needed; answer was incorrect otherwise
        return v

    # Returns the vector orthogonal to both input vectors - tested in vector3_cross_test.py
    @classmethod
    def cross_product(cls, v1, v2):
        v3a = v1.b * v2.c - v1.c * v2.b
        v3b = v1.c * v2.a - v1.a * v2.c
        v3c = v1.a * v2.b - v1.b * v2.a
        return Vector3(v3a, v3b, v3c)

    # Returns the dot product of two vectors - tested in vector3_dot_test.py
    @classmethod
    def dot_product(cls, v1, v2):
        return v1.a * v2.a + v1.b * v2.b + v1.c * v2.c

    # This function determines the angle between two vectors using the dot product of the normed inputs and acos. Output
    # is in radians - evaluated in vector3_angle_test.py
    @classmethod
    def angle(cls, v1, v2):
        v1 = v1.normed
        v2 = v2.normed
        dot = cls.dot_product(v1, v2)
        return math.acos(dot)

# Quaternions

class Quaternion:

    # Initialization

    def __init__(self, a, b, c, d):
        self.a = a  # the scalar component
        self.b = b  # quaternionic i component
        self.c = c  # quaternionic j component
        self.d = d  # quaternionic k component

    # Returns a scaled version of the quaternion, where every element has been multiplied by some scalar variable
    # - tested in quaternion_scale_test.py
    def scale(self, scalar):
        return Quaternion(self.a * scalar, self.b * scalar, self.c * scalar, self.d * scalar)

    # Properties

    # Return the quaternion equivalent of a complex conjugate - tested in quaternion_pure_and_rotations_test.py
    @property
    def conjugate(self):
        return Quaternion(self.a, -1 * self.b, -1 * self.c, -1 * self.d)

    # Return the magnitude of a quaternion
    @property
    def norm(self) -> float:
        return math.sqrt((self.a ** 2 + self.b ** 2 + self.c ** 2 + self.d ** 2))

    # Return the a quaternion with magnitude 1, thus an element of SU(2) and member of SO(3) - tested in quaternion_pure_and_rotations_test.py
    @property
    def normed(self):
        return self.scale(scalar=(1 / self.norm))

    # Class Methods

    # Sums n quaternions
    @classmethod
    def sum(cls, *args):
        q = copy.copy(args[0])

        for j in args[1:]:
            a = q.a + j.a
            b = q.b + j.b
            c = q.c + j.c
            d = q.d + j.d
            q.a, q.b, q.c, q.d = a, b, c, d  # Not too sure why this final line is needed; answer was incorrect otherwise
        return q

    # Returns the difference of n quaternions
    @classmethod
    def difference(cls, *args):
        q = copy.copy(args[0])

        for j in args[1:]:
            a = q.a - j.a
            b = q.b - j.b
            c = q.c - j.c
            d = q.d - j.d
            q.a, q.b, q.c, q.d = a, b, c, d  # Not too sure why this final line is needed; answer was incorrect otherwise
        return q

    # Returns the quaternionic product of n quaternions - tested in quaternion_pure_and_rotations_test.py
    @classmethod
    def product(cls, *args):
        q = copy.copy(args[0])

        for j in args[1:]:
            a = (q.a * j.a) - (q.b * j.b) - (q.c * j.c) - (q.d * j.d)
            b = (q.a * j.b) + (q.b * j.a) + (q.c * j.d) - (q.d * j.c)
            c = (q.a * j.c) - (q.b * j.d) + (q.c * j.a) + (q.d * j.b)
            d = (q.a * j.d) + (q.b * j.c) - (q.c * j.b) + (q.d * j.a)
            q.a, q.b, q.c, q.d = a, b, c, d  # Not too sure why this final line is needed; answer was incorrect otherwise
        return q

    # Return a quaternion form of a vector in R3 - tested in quaternion_pure_and_rotations_test.py
    @classmethod
    def pure_qt(cls, vector=Vector3):
        return Quaternion(0, vector.a, vector.b, vector.c)

    # Rotates a point using a quaternion - tested in quaternion_pure_and_rotations_test.py
    @classmethod
    def rotate(cls, q, p=Vector3):
        if q.norm < 1.00000001 and q.norm > 0.99999999:  # manual control over float error
            qd = q.conjugate
            p = cls.pure_qt(p)
            qpqd = cls.product(q, p, qd)
            return Vector3(qpqd.b, qpqd.c, qpqd.d)
        else:
            raise ArithmeticError

    # Generates a rotation about an axis; based off the syntax from point_rotation, which was tested in quaternion_pure_and_rotations_test.py
    @classmethod
    def axis_rotation(cls, angle=float, axis=Vector3):
        angle *= 0.5
        axis = axis.normed
        axis = axis.scale(math.sin(angle))
        q = Quaternion(math.cos(angle), axis.a, axis.b, axis.c)
        return q

    # Generates the rotation quaternion that will rotate point p1 to point p2
    @classmethod
    def point_rotation(cls, p1=Vector3, p2=Vector3):
        angle = Vector3.angle(p1, p2) * 0.5
        axis = Vector3.cross_product(p1, p2).normed
        axis = axis.scale(math.sin(angle))
        q = Quaternion(math.cos(angle), axis.a, axis.b, axis.c)
        return q

# Complex Quaternions

class QtComplex:

    # Initialization

    def __init__(self, c1, c2, c3, c4):
        self.c1 = c1  # first complex element
        self.c2 = c2  # second complex element
        self.c3 = c3  # third complex element
        self.c4 = c4  # fourth complex element

    # Returns the complex linear combination (CLC) notation for the complex quaternion
    @property
    def CLC(self):
        string = f'{self.c1, self.c2, self.c3, self.c4}'
        return string

    # Returns the real linear combination (RLC) notation for the complex quaternion
    @property
    def RLC(self):
        string = f'{self.c1.real, self.c1.imag, self.c2.real, self.c3.real, self.c4.real, self.c2.imag, self.c3.imag, self.c4.imag}'
        return string

    # Returns a complex quaternion whose quaternionic elements are negated; in CLC, these are the last three elements,
    # in RLC it is the last six
    @property
    def quaternion_conjugate(self):
        return QtComplex(self.c1, self.c2 * -1, self.c3 * -1, self.c4 * -1)

    # Returns a complex quaternion whose complex i values are negated; this is the imaginary component of each element
    # in CLC notation, and the 2nd - 5th element in RLC notation
    @property
    def complex_conjugate(self):
        c1 = Complex.conjugate(self.c1)
        c2 = Complex.conjugate(self.c2)
        c3 = Complex.conjugate(self.c3)
        c4 = Complex.conjugate(self.c4)
        return QtComplex(c1, c2, c3, c4)

    # Returns the both the complex and quaternionic conjugate in one complex quaternion
    @property
    def hermitian_conjugate(self):
        c1 = Complex.conjugate(self.c1)
        c2 = Complex.conjugate(self.c2) * -1
        c3 = Complex.conjugate(self.c3) * -1
        c4 = Complex.conjugate(self.c4) * -1
        return QtComplex(c1, c2, c3, c4)

    # Class Methods

    # Allows definition of a complex quaternion through a real linear combination
    @classmethod
    def real_linear(cls, a, b, i, j, k, ii, ij, ik):
        c1 = complex(a, b)
        c2 = complex(i, ii)
        c3 = complex(j, ij)
        c4 = complex(k, ik)
        return QtComplex(c1, c2, c3, c4)

    # The complex quaternion multiplicative product
    @classmethod
    def product(cls, *args):
        cq = copy.copy(args[0])

        for j in args[1:]:
            c1 = (cq.c1 * j.c1) - (cq.c2 * j.c2) - (cq.c3 * j.c3) - (cq.c4 * j.c4)
            c2 = (cq.c1 * j.c2) + (cq.c2 * j.c1) + (cq.c3 * j.c4) - (cq.c4 * j.c3)
            c3 = (cq.c1 * j.c3) - (cq.c2 * j.c4) + (cq.c3 * j.c1) + (cq.c4 * j.c2)
            c4 = (cq.c1 * j.c4) + (cq.c2 * j.c3) - (cq.c3 * j.c2) + (cq.c4 * j.c1)
            cq.c1, cq.c2, cq.c3, cq.c4 = c1, c2, c3, c4

        return cq

class DualQuaternion:
    def __init__(self, a, b, c, d, e, ei, ej, ek):
        self.a = a
        self.b = b
        self.c = c
        self.d = d
        self.e = e
        self.ei = ei
        self.ej = ej
        self.ek = ek

    @property
    def ELC(self):
        string = f'{self.a, self.b, self.c, self.d, self.e, self.ei, self.ej, self.ek}'
        return string

    @property
    def QTA(self):
        string = f'{self.a, self.b, self.c, self.d}'
        return

    @property
    def QTB(self):
        string = f'{self.e, self.ei, self.ej, self.ek}'
        return

    @property
    def dualQuaternionConjugate(self):
        a = self.a
        b = -1 * self.b
        c = -1 * self.c
        d = -1 * self.d
        e = self.e
        ei = -1 * self.ei
        ej = -1 * self.ej
        ek = -1 * self.ek
        return DualQuaternion(a, b, c, d, e, ei, ej, ek)

    @property
    def dualNumberConjugate(self):
        a = self.a
        b = self.b
        c = self.c
        d = self.d
        e = -1 * self.e
        ei = -1 * self.ei
        ej = -1 * self.ej
        ek = -1 * self.ek
        return DualQuaternion(a, b, c, d, e, ei, ej, ek)

    @property
    def fullConjugate(self):
        a = self.a
        b = -1 * self.b
        c = -1 * self.c
        d = -1 * self.d
        e = -1 * self.e
        ei = self.ei
        ej = self.ej
        ek = self.ek
        return DualQuaternion(a, b, c, d, e, ei, ej, ek)

    # Sums n dual quaternions
    @classmethod
    def sum(cls, *args):
        q = copy.copy(args[0])

        for j in args[1:]:
            a = q.a + j.a
            b = q.b + j.b
            c = q.c + j.c
            d = q.d + j.d
            e = q.e + j.e
            ei = q.ei + j.ei
            ej = q.ej + j.ej
            ek = q.ek + j.ek
            q.a, q.b, q.c, q.d, q.e, q.ei, q.ej, q.ek = a, b, c, d, e, ei, ej, ek
        return q

    # Returns the difference of n dual quaternions
    @classmethod
    def difference(cls, *args):
        q = copy.copy(args[0])

        for j in args[1:]:
            a = q.a - j.a
            b = q.b - j.b
            c = q.c - j.c
            d = q.d - j.d
            e = q.e - j.e
            ei = q.ei - j.ei
            ej = q.ej - j.ej
            ek = q.ek - j.ek
            q.a, q.b, q.c, q.d, q.e, q.ei, q.ej, q.ek = a, b, c, d, e, ei, ej, ek
        return q

    @classmethod
    def product(cls, *args):
        q = copy.copy(args[0])

        for j in args[1:]:

            # elements of first quaternion in dual quaternion product

            a = (q.a * j.a) - (q.b * j.b) - (q.c * j.c) - (q.d * j.d)
            b = (q.a * j.b) + (q.b * j.a) + (q.c * j.d) - (q.d * j.c)
            c = (q.a * j.c) - (q.b * j.d) + (q.c * j.a) + (q.d * j.b)
            d = (q.a * j.d) + (q.b * j.c) - (q.c * j.b) + (q.d * j.a)

            # elements of the second quaternion in dual quaternion product

            e = ((q.a * j.e) - (q.b * j.ei) - (q.c * j.ej) - (q.d * j.ek)) + ((q.e * j.a) - (q.ei * j.b) - (q.ej * j.c) - (q.ek * j.d))
            ei = ((q.a * j.ei) + (q.b * j.e) + (q.c * j.ek) - (q.d * j.ej)) + ((q.e * j.b) + (q.ei * j.a) + (q.ej * j.d) - (q.ek * j.c))
            ej = ((q.a * j.ej) - (q.b * j.ek) + (q.c * j.e) + (q.d * j.ei)) + ((q.e * j.c) - (q.ei * j.d) + (q.ej * j.a) + (q.ek * j.b))
            ek = ((q.a * j.ek) + (q.b * j.ej) - (q.c * j.ei) + (q.d * j.e)) + ((q.e * j.d) + (q.ei * j.c) - (q.ej * j.b) + (q.ek * j.a))

            # redefine q values to new calculated ones

            q.a, q.b, q.c, q.d, q.e, q.ei, q.ej, q.ek = a, b, c, d, e, ei, ej, ek

        return q


##### LINEAR REGRESSION - PSEUDOINVERSION #####

import numpy as np
import matplotlib.pyplot as plt
from scipy import stats             # for verification
from sklearn import linear_model    # for verification
from sklearn.metrics import mean_squared_error, r2_score

data = np.loadtxt('data.txt')       # shape (50, 2)

x = data[:, 0]      # shape (50,)
y = data[:, 1]      # shape (50,)

plt.figure(1, figsize=(10, 8), dpi=100, facecolor='w', edgecolor='k')
plt.scatter(x, y, color='purple', label='original data')

### Pseudoinversion method

print("Pseudoinversion method")

X = np.ones((data.shape[0], 1))
X = np.concatenate((X, x[:, np.newaxis]), axis=1)

theta_optimal = np.dot(np.dot(np.linalg.inv(np.dot(X.T, X)), X.T), y)       # shape (2,)

y_hat = theta_optimal[0] + theta_optimal[1] * x

plt.plot(x, y_hat, 'g-', linewidth=7.0, label = 'pseudoinv fitted line')

print("theta_optimal:", theta_optimal)      # [-10.61262592, 6.90359569]
print("R-squared:", r2_score(y, y_hat))     # 0.96

### Verification

# Scipy
print("\nScipy")
slope, intercept, r_value, p_value, std_err = stats.linregress(x, y)
print("intercept, slope:", intercept, slope)
#print(np.allclose(theta_optimal, [intercept, slope]))
y_pred = intercept + slope * x
plt.plot(x, y_pred, color='red', linewidth=3.0, label = 'scipy fitted line')
print("R-squared:", r_value**2)             # 0.96
print("R-squared:", r2_score(y, y_pred))    # 0.96

# scikit-learn Linear Regression
print("\nscikit-learn Linear Regression")
reg = linear_model.LinearRegression()
reg.fit(x.reshape(-1, 1), y)
y_pred = reg.predict(x.reshape(-1, 1))
plt.plot(x, y_pred, color='black', linestyle='-', linewidth=1.0, label = 'scikit LR fitted line')
print("intercept, slope:", reg.intercept_, reg.coef_)
print("R-squared:", r2_score(y, y_pred))    # 0.96

# scikit-learn Ridge
print("\nscikit-learn Ridge")
clf = linear_model.Ridge()
clf.fit(x[:, np.newaxis], y)
y_pred = clf.predict(x[:, np.newaxis])
plt.plot(x, y_pred, color='orange', linestyle='', marker='2', label = 'scikit Ridge fitted line')
print("intercept, slope:", clf.intercept_, clf.coef_)
print("R-squared:", r2_score(y, y_pred))    # 0.96

plt.xlabel('data')
plt.ylabel('target')
plt.legend()

plt.figure(2, figsize=(10, 8), dpi=100, facecolor='w', edgecolor='k')
plt.scatter(x, y, color='purple', label='original data')
plt.plot(x, y_hat, 'k-', linewidth=2.0, label = 'pseudoinv fitted line')

# SGD works better with features centered around zero, with standard deviation of 1.
mean, std = x.mean(), x.std()
x_scaled = (x - mean) / std

# scikit-learn SGDRegressor
print("\nscikit-learn SGDRegressor")
clf = linear_model.SGDRegressor(loss="squared_loss", penalty="l2", max_iter=1000, tol=1e-3, shuffle=True)
clf.fit(x_scaled[:, np.newaxis], y)
y_pred = clf.predict(x_scaled[:, np.newaxis])
plt.plot(x, y_pred, color='yellow', linestyle='-', linewidth=1.0, label = 'scikit SGDRegressor fitted line')
print("intercept, slope:", clf.intercept_, clf.coef_)
print("R-squared:", r2_score(y, y_pred))    # 0.96

plt.xlabel('data')
plt.ylabel('target')
plt.legend()

plt.show()


import numpy as N
from math import *

class MCOptionPricer(object):
    def __init__(self, S=100.0, K=100.0, sigma=0.25, r=0.05, days=260, paths=10000):
        self.S = S
        self.K = K
        self.sigma = sigma
        self.r = r
        self.days = days
        self.paths = paths
        self.h = 1.0/self.days
        self.const1 = exp((self.r-0.5*self.sigma**2)*self.h)
        self.const2 = self.sigma*sqrt(self.h)

    def run(self):
        stock_price = self.S*N.ones(self.paths, dtype='float64')
        stock_price_sum = N.zeros(self.paths, dtype='float64')
        for j in range(self.days):
            growth_factor = self.const1*N.exp(self.const2*N.random.standard_normal(self.paths))
            stock_price = stock_price*growth_factor
            stock_price_sum = stock_price_sum + stock_price
        stock_price_avg = stock_price_sum/self.days
        zeros = N.zeros(self.paths, dtype='float64')
        r_factor = exp(-self.r*self.h*self.days)
        self.vanilla_put = r_factor*N.mean(N.maximum(zeros,self.K-stock_price))
        self.asian_put = r_factor*N.mean(N.maximum(zeros,self.K-stock_price_avg))
        self.vanilla_call = r_factor*N.mean(N.maximum(zeros,stock_price-self.K))
        self.asian_call = r_factor*N.mean(N.maximum(zeros,stock_price_avg-self.K))

def main():
    op = MCOptionPricer()
    op.run()
    print "Vanilla Put Price = ", op.vanilla_put
    print "Asian Put Price = ", op.asian_put
    print "Vanilla Call Price = ", op.vanilla_call
    print "Asian Call Price = ", op.asian_call

if __name__ == '__main__':
    main()


# by Huaiyu TAN

import numpy as np
def is_dd(M: list):
    p = 0
    for i in range(len(M)):
        if np.sum(np.abs(M[i]))-np.abs(M[i][i]) >= np.abs(M[i][i]):
            p += 1
    if p == 0:
        print("The Matrix is diagonally dominant !")
    else:
        print("The Matrix is not diagonally dominant !")
    return p

M = np.array([[3,2,0],[-4,-20,-6],[7,1,9]])
p = is_dd(M)


import matplotlib.pyplot as plt
from skimage import io
from skimage import img_as_float
import numpy as np
import numpy.matlib
import math

file_name='tripod.png';
img=io.imread(file_name)

img = img_as_float(img)

row, col, channel = img.shape

# set the parameters
radius = 100.0
angle = math.pi/3
angle2 = math.pi/4
sides = 10.0
# set the center of the circle, proportion of the image size
centerX = 0.5
centerY = 0.5

iWidth=col
iHeight=row

center_x=iWidth*centerX
center_y=iHeight*centerY

xx = np.arange (col)
yy = np.arange (row)

x_mask = numpy.matlib.repmat (xx, row, 1)
y_mask = numpy.matlib.repmat (yy, col, 1)
y_mask = np.transpose(y_mask)

xx_dif = x_mask - center_x
yy_dif = y_mask - center_y

r = np.sqrt(xx_dif * xx_dif + yy_dif * yy_dif)
theta = np.arctan2(yy_dif, xx_dif+0.0001) - angle - angle2
temp_theta=theta/math.pi*sides*0.5
temp_r = np.mod(temp_theta, 1.0)
mask_1 = temp_r < 0.5
theta = temp_r * 2 * mask_1 + (1-temp_r) * 2 * (1 - mask_1)

radius_c=radius/np.cos(theta)

temp_r = np.mod (r/radius_c, 1.0)
mask_1 = temp_r < 0.5
r = radius_c * (temp_r * 2 * mask_1 + (1-temp_r) * 2 * (1 - mask_1))

theta = theta + angle

x1_mask = r * np.cos(theta) + center_x
y1_mask = r * np.sin(theta) + center_y

mask = x1_mask < 0
x1_mask = x1_mask * (1 - mask)
mask = x1_mask > (col - 1)
x1_mask = x1_mask * (1 - mask) + (x1_mask * 0 + col -2) * mask

mask = y1_mask < 0
y1_mask = y1_mask * (1 - mask)
mask = y1_mask > (row -1)
y1_mask = y1_mask * (1 - mask) + (y1_mask * 0 + row -2) * mask

img_out = img * 1.0

int_x = np.floor (x1_mask)
int_x = int_x.astype(int)
int_y = np.floor (y1_mask)
int_y = int_y.astype(int)

p_mask = x1_mask - int_x
q_mask = y1_mask - int_y

img_out = img * 1.0

for ii in range(row):
    for jj in range (col):
        new_xx = int_x [ii, jj]
        new_yy = int_y [ii, jj]
#        p = p_mask[ii, jj]
#        q = q_mask[ii, jj]

        img_out[ii, jj, :] = img[new_yy, new_xx, :]

plt.figure (1)
plt.imshow (img)
plt.axis('off')

plt.figure (2)
plt.imshow (img_out)
plt.axis('off')

plt.show()


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

import projgrad

import sys
sys.path.append('../lib')
import plotting
from optdynlib import *

plt.style.use(['../optdynim.mplstyle'])

sigma = 0.025
#Delta = 0.1
Delta = 2.0 * sigma
N = int(1.0/Delta)
# ensure N is always even
N = N if N % 2 == 0 else N+1
x = np.linspace(0.0, 1.0, N, endpoint=False)
def func(x, sigma):
    return np.exp(- x**2 /  (2.0 * sigma**2))
F = build_1d_frp_matrix(func, x, sigma*np.ones(len(x)))

fig, ax = plt.subplots()

i = N//2
dp = np.linalg.inv(F).dot(ei(N, i))
dp /= np.sum(dp)

ax.plot((x-0.5)/sigma, dp, 'o-', label='$F^{-1} e_a$')

sigmacorr = 2*sigma
dpcorr = np.linalg.inv(F).dot(np.exp(-(Delta*(np.arange(N)-i))**2/(2*sigmacorr**2)))
dpcorr /= np.sum(dpcorr)
ax.plot((x-0.5)/sigma, dpcorr, 'o-', label='$F^{-1} f_a$')
ax.set_xlabel('$x/\sigma$')
ax.set_ylabel('relative update')
ax.set_xlim(-10, 10)
ax.legend()
plotting.despine(ax)
fig.tight_layout()
fig.savefig('figS4.svg')
fig.savefig('figS4.png', dpi=300)


import math as m
import numpy as np

def theFunction(x):
    return x**4 - 2*x + 1

n = 10
limite_inferior = 0
limite_superior = 2
delta_x = (limite_superior - limite_inferior) / n

# integral simple
suma = 0
for i in range(1, n):
    suma += theFunction(limite_inferior + i * delta_x)

suma = delta_x * (0.5*(theFunction(limite_inferior) +
                       theFunction(limite_superior)) + suma)
print('for loop', suma)

# regla simpson
suma_1 = 0
for i in range(1, (int)(n / 2) + 1):
    suma_1 += theFunction(limite_inferior + (2 * i - 1) * delta_x)

suma_2 = 0
for i in range(1, (int)(n / 2)):
    suma_2 += theFunction(limite_inferior + 2 * i * delta_x)

suma = (1/3) * delta_x * (theFunction(limite_inferior) + theFunction(limite_superior) + 4 * suma_1 + 2 * suma_2)
print('simpson', suma)


import numpy as np
def sumDivisors(x):
    sum = 1
    j = x
    sqrt = int(np.sqrt(x))
    for i in range(2, sqrt):
        if j%i==0:
            #print(j, i, j/i)
            sum = sum + i
            sum = sum + (j/i)
    if sqrt*sqrt == x:
        sum = sum - sqrt
    #print(sum)
    return sum

def isAmicable(a, b):
    if sumDivisors(a) == b and sumDivisors(b) == a:
        return True
    else:
        return False
"""
def main():
    print(sumDivisors(8039))
    print(isAmicable(2,3))
"""
def main():
    sum = 0
    for i in range(1, 10000):
        for j in range(i+1, 10000):
            truth = isAmicable(i, j)
            if truth == True:
                print(i, j)
                sum = sum + i + j
    print(sum)

if __name__=="__main__":
    main()


import math
import numpy as np
from scipy.io import wavfile

print("Press 1 for sin wave")
print("Press 2 for cosine wave")
print("Press 3 for using custom audio file (wav format)")
opt = int(input("Enter option: "))

file = open("data.txt", "w+")

if (opt == 1):
    for i in np.linspace(0, 1, int(input("Enter number of elements: "))):
        file.writelines(str(math.sin(2*math.pi*2000*i))+"\n")
elif (opt == 2):
    for i in np.linspace(0, 1, int(input("Enter number of elements: "))):
        file.writelines(str(math.cos(2*math.pi*2000*i))+"\n")
elif (opt == 3):
    file_name = input("Enter audio file name: ")
    samplerate, data = wavfile.read(file_name)
    for i in data:
        file.writelines(str(i[0]) + "\n")


import numpy as np

def chol_factor(M):
    '''
    Cholesky LL' factorization.

    Input:
      M : input matrix
    Output
      L : lower triangular matrix (such that M=L*L')
    '''
    n = len(M)
    L = np.zeros((n, n))
    for i in range(0, n):
        val = M[i, i] - np.dot(L[i, :],L[i, :])
        if val < 0:
            raise Exception('The matrix is not positive definite')
        L[i, i] = np.sqrt(val)
        for j in range(i+1, n):
            L[j, i] = (M[j, i] - np.dot(L[i, :],L[j, :])) / L[i, i]
    return L


#Calculating Probability Density Function and Cumulative distribution Function

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

x = np.linspace(-6,6,1000)

fx = norm.pdf(x, loc=0,scale =1)
# loc: mean scale: sd, use cdf instad of pdf for cdf and logpdf, logcdf

plt.plot(x,fx)
plt.show()


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

import numpy as np
from utils.ply import write_ply, read_ply
import time

def compute_plane(points):
    """
    Computing a plane passing through 3 input points

    Parameters
    ----------
    points : 3x3 numpy array (3 points stacked in a row-wise way)

    Returns
    -------
    point : a point in the found plane
    normal : a unit normal vector of the found plane
    """

    normal = np.cross(points[1] - points[0], points[2] - points[0])
    normal = normal / np.sqrt(np.sum(normal**2))

    point = points[0]

    return point, normal

def in_plane(points, normals, ref_pt, ref_normal, threshold_in=0.1, threshold_normals=0.8):
    """
    Checks whether the given points belong to a given plane (with some threshold value)

    Parameters
    ----------
    points : Nx3 numpy array
    normals : estimation of local normals at each point
    ref_pt : 3-numpy array (a point of the plane)
    ref_normal : 3-numpy array (unit vector of the plane)
    threshold_in : float: maximum distance to the plane for points to belong to it
    threshold_normals : float : if normals is provided, the angle between the normals of the plane
                        should not be greater than this threshold

    Returns
    -------
    indices : N-numpy array of booleans telling which points belong to the plane
    """
    dists = np.einsum("i,ji->j", ref_normal, points - ref_pt)
    indices = abs(dists) < threshold_in
    if normals is not None:
        normal_check = abs(np.dot(ref_normal, normals.T)) > threshold_normals
        return indices & normal_check
    return indices

def RANSAC(points, normals=None, NB_RANDOM_DRAWS=100, threshold_in=0.1, threshold_normals=0.8):
    """
    Applies the RANSAC algorithm to find an horizontal plane

    Parameters
    ----------
    points : Nx3 numpy array
    normals: Nx3 numpy array, optional (estimation of local normals at each point)
    NB_RANDOM_DRAWS : number of tries: the biggest plane of all draws will be taken
    threshold_in : float : distance threshold telling whether a point belongs to a plane or not
    threshold_normals : float : if normals is provided, the angle between the normals of the plane
                        should not be greater than this threshold, moreover the projection of the
                        normal of the plane on z axis should be greater than this threshold

    Returns
    -------
    best_ref_pt : 3-numpy array (point belonging to the best found plane)
    best_normal : 3-numpy array (unit normal vector of the best found plane)
    """

    best_ref_pt = np.zeros((3,1))
    best_normal = np.zeros((3,1))
    best_nb = -1

    for i in range(NB_RANDOM_DRAWS):
        # Drawing 3 different point indices at random
        rand_indices = np.zeros(3).astype(int)
        while len(np.unique(rand_indices)) != 3:
            rand_indices = np.random.randint(0, np.shape(points)[0], size=3)

        # Extracting the corresponding points
        pts = points[rand_indices]

        # Finding the associated plane
        ref_pt, ref_normal = compute_plane(pts)

        # Couting the number of points in this plane
        nb = np.sum(in_plane(points, normals, ref_pt, ref_normal, threshold_in))

        # Updating the best plane if needed
        if nb > best_nb and abs(ref_normal[2]) > threshold_normals:
            best_nb = nb
            best_ref_pt = ref_pt
            best_normal = ref_normal

    return best_ref_pt, best_normal


import numpy as np
import pandas as pd

def sigmoid(x):
    return 1/(1+np.exp(-x))

def softmax(x):
    x = x - x.max(axis=1, keepdims=True)
    return np.exp(x)/np.sum(np.exp(x),axis=1, keepdims=True)

df = pd.read_csv("adult.data.txt", names=["age","workclass","fnlwgt","education","education-num","marital-status"
    ,"occupation","relationship","race","sex","capital-gain","capital-loss","hours-per-week","native-country","class"])
dx = pd.read_csv("adult.test.txt", names=["age","workclass","fnlwgt","education","education-num","marital-status"
    ,"occupation","relationship","race","sex","capital-gain","capital-loss","hours-per-week","native-country","class"])

for lf in df:
    if df[lf].dtype == "object":
        df[lf] = df[lf].astype("category").cat.codes
        dx[lf] = dx[lf].astype("category").cat.codes
    else :
        df[lf] = (df[lf] - df[lf].mean())/(df[lf].max() - df[lf].min())
        dx[lf] = (dx[lf] - dx[lf].mean()) / (dx[lf].max() - dx[lf].min())

x = df.drop(columns=["class"])
y = df["class"].values
x_test = dx.drop(columns=["class"])
y_test = dx["class"].values

multi_y = np.zeros((y.size, y.max()+1))
multi_y[np.arange(y.size), y] = 1
multi_y_test = np.zeros((y_test.size, y_test.max()+1))
multi_y_test[np.arange(y_test.size), y_test] = 1

inputSize = len(x.columns)
numberOfNodes = 150
numberOfClass = y.max() + 1
numberOfExamples = x.shape[0]

w1 = np.random.random_sample(size=(inputSize, numberOfNodes))
b1 = np.random.random_sample(numberOfNodes)
w2 = np.random.random_sample(size=(numberOfNodes, numberOfClass))
b2 = np.random.random_sample(numberOfClass)

batchSize = 32
trainNum = 150
learningRate = 0.01

# Start Training
for k in range(trainNum + 1):
    cost = 0
    accuracy = 0
    for i in range(int(numberOfExamples/batchSize)):
        # Forward-Propagation
        z = x[i * batchSize : (i+1) * batchSize]
        z_y = multi_y[i * batchSize : (i+1) * batchSize]
        layer1 = np.matmul(z, w1) + b1
        sig_layer1 = sigmoid(layer1)
        layer2 = np.matmul(sig_layer1, w2) + b2
        soft_layer2 = softmax(layer2)
        pred = np.argmax(soft_layer2, axis=1)
        # Cost Function: Cross-Entropy loss
        cost += -(z_y * np.log(soft_layer2 + 1e-9) + (1-z_y) * np.log(1 - soft_layer2 + 1e-9)).sum()
        accuracy += (pred == y[i * batchSize : (i + 1) * batchSize]).sum()

        # Back-Propagation
        dlayer2 = soft_layer2 - multi_y[i * batchSize : (i+1) * batchSize]
        dw2 = np.matmul(sig_layer1.T, dlayer2) / batchSize
        db2 = dlayer2.mean(axis=0)
        dsig_layer1 = (dlayer2.dot(w2.T))
        dlayer1 = sigmoid(layer1) * (1 - sigmoid(layer1)) * dsig_layer1
        dw1 = np.matmul(z.T, dlayer1) / batchSize
        db1 = dlayer1.mean(axis=0)

        w2 -= learningRate * dw2
        w1 -= learningRate * dw1
        b2 -= learningRate * db2
        b1 -= learningRate * db1
    if k % 10 == 0 :
        print("-------- # : {} ---------".format(k))
        print("cost: {}".format(cost/numberOfExamples))
        print("accuracy: {} %".format(accuracy/numberOfExamples * 100))

# Test the trained model
test_cost = 0
test_accuracy = 0
# Forward-Propagation
layer1 = np.matmul(x_test, w1) + b1
sig_layer1 = sigmoid(layer1)
layer2 = np.matmul(sig_layer1, w2) + b2
soft_layer2 = softmax(layer2)
pred = np.argmax(soft_layer2, axis=1)
# Cost Function: Cross-Entropy loss
test_cost += -(multi_y_test * np.log(soft_layer2 + 1e-9) + (1-multi_y_test) * np.log(1 - soft_layer2 + 1e-9)).sum()
test_accuracy += (pred == y_test).sum()

print("---- Result of applying test data to the trained model")
print("cost: {}".format(test_cost/numberOfExamples))
print("accuracy: {} %".format(test_accuracy/numberOfExamples * 100))


#Vamos utilizar a formula de black scholes merton para derivativos no mercado de opcoes
import numpy as np
import pandas as pd
from pandas_datareader import data as wb
from scipy.stats import norm

#Vamos utilizar as formulas do d1 e d2 para efetuar o calculo de BSM
#S = preço da acao
#K = preco de exercicio
#r = taxa livre de risco
#stdev = desvio padrao
#T = intervalo de tempo (anos)

def d1(S, K, r, stdev, T):
    return (np.log(S/K) + (r + stdev ** 2 / 2) * T) / (stdev * np.sqrt(T))

def d2(S, K, r, stdev, T):
    return (np.log(S/K) + (r - stdev ** 2 / 2) * T) / (stdev * np.sqrt(T))

#Vamos utilizar a distribuiçao normal cumulativa (cdf)
#Mostra como os dados se acumulam no tempo
#norm.cdf(0)

def BSM(S, K, r, stdev, T):
    return (S * norm.cdf(d1(S, K, r, stdev, T))) - (K * np.exp(-r * T) * norm.cdf(d2(S, K, r, stdev, T)))

ticker = 'PG'
data = pd.DataFrame()
data[ticker] = wb.DataReader(ticker, data_source='yahoo', start='2007-1-1', end='2017-3-21')['Adj Close']

S = data.iloc[-1]
log_returns = np.log(1 + data.pct_change())

stdev = log_returns.std() * 250 ** 0.5

#Aqui estamos atribuindo valores para os parametros
r = 0.025
K = 110.0
T = 1


import numpy as np
from scipy.constants import mu_0, epsilon_0

# useful params
def omega(freq):
    """Angular frequency, omega"""
    return 2.*np.pi*freq

def k(freq, sigma, mu=mu_0, eps=epsilon_0):
    """ Eq 1.47 - 1.49 in Ward and Hohmann """
    w = omega(freq)
    alp  = w * np.sqrt( mu*eps/2 * ( np.sqrt(1. + (sigma / (eps*w))**2 ) + 1) )
    beta = w * np.sqrt( mu*eps/2 * ( np.sqrt(1. + (sigma / (eps*w))**2 ) - 1) )
    return alp - 1j*beta

def TriangleFun(time, ta, tb):
    """
        Triangular Waveform
        * time: 1D array for time
        * ta: time at peak
        * tb: time at step-off
    """
    out = np.zeros(time.size)
    out[time<=ta] = 1/ta*time[time<=ta]
    out[(time>ta)&(time<tb)] = -1/(tb-ta)*(time[(time>ta)&(time<tb)]-tb)
    return out

def TriangleFunDeriv(time, ta, tb):
    """
        Derivative of Triangular Waveform
    """
    out = np.zeros(time.size)
    out[time<=ta] = 1/ta
    out[(time>ta)&(time<tb)] = -1/(tb-ta)
    return out

def SineFun(time, ta):
    """
        Sine Waveform
        * time: 1D array for time
        * ta: Pulse Period
    """
    out = np.zeros(time.size)
    out[time<=ta] = np.sin(1./ta*np.pi*time[time<=ta])

    return out

def SineFunDeriv(time, ta):
    """
        Derivative of Sine Waveform
    """
    out = np.zeros(time.size)
    out[time<=ta] = 1./ta*np.pi*np.cos(1./ta*np.pi*time[time<=ta])
    return out

def VTEMFun(time, ta, tb, a):
    """
        VTEM Waveform
        * time: 1D array for time
        * ta: time at peak of exponential part
        * tb: time at step-off
    """
    out = np.zeros(time.size)
    out[time<=ta] = (1-np.exp(-a*time[time<=ta]/ta))/(1-np.exp(-a))
    out[(time>ta)&(time<tb)] = -1/(tb-ta)*(time[(time>ta)&(time<tb)]-tb)
    return out


# -*- coding: UTF-8 -*-
# !/usr/bin/python
# @time     :2019/4/3 10:36
# @author   :Mo
# @function :TS-SS distance
# @url      :https://github.com/taki0112/Vector_Similarity
# @paper    :A Hybrid Geometric Approach for Measuring Similarity Level Among Documents and Document Clustering

import numpy as np
import math

zero_bit = 0.000000001

def Cosine(vec1, vec2):
    """
       余弦相似度
    :param vec1: arrary
    :param vec2: arrary
    :return: float
    """
    result = InnerProduct(vec1, vec2) / (VectorSize(vec1) * VectorSize(vec2) + zero_bit)
    return result

def VectorSize(vec):
    vec_pow = sum(math.pow(v + zero_bit, 2) for v in vec)
    if vec_pow >= 0:
        return math.sqrt(vec_pow)
    else:
        return zero_bit

def InnerProduct(vec1, vec2):
    try:
        return sum(v1 * v2 for v1, v2 in zip(vec1, vec2))
    except:
        return zero_bit

def Euclidean(vec1, vec2):
    vec12_pow = sum(math.pow((v1 - v2), 2) for v1, v2 in zip(vec1, vec2))
    if vec12_pow >= 0:
        return math.sqrt(vec12_pow)
    else:
        return zero_bit

def Theta(vec1, vec2):
    cosine_vec12 = Cosine(vec1, vec2)
    if -1 <= cosine_vec12 and cosine_vec12 <= 1:
        return math.acos(cosine_vec12) + 10
    else:
        return zero_bit + 10

def Triangle(vec1, vec2):
    theta = math.radians(Theta(vec1, vec2))
    return (VectorSize(vec1) * VectorSize(vec2) * math.sin(theta)) / 2

def Magnitude_Difference(vec1, vec2):
    return abs(VectorSize(vec1) - VectorSize(vec2))

def Sector(vec1, vec2):
    ED = Euclidean(vec1, vec2)
    MD = Magnitude_Difference(vec1, vec2)
    theta = Theta(vec1, vec2)
    return math.pi * math.pow((ED + MD), 2) * theta / 360

def TS_SS(vec1, vec2):
    return Triangle(vec1, vec2) * Sector(vec1, vec2)

if __name__ == '__main__':
    vec1_test = np.array([1, 38, 17, 32])
    vec2_test = np.array([5, 6, 8, 9])

    print(Euclidean(vec1_test, vec2_test))
    print(Cosine(vec1_test, vec2_test))
    print(TS_SS(vec1_test, vec2_test))


from __future__ import print_function, division

import numpy as np

def gram_schmidt(ws):
    vs = ws.copy()
    num_vectors = ws.shape[1]
    # orthogonize
    for i in range(num_vectors):
        for j in range(i):
            vs[:, i] -= vs[:, j].dot(ws[:, i])/(vs[:, j].dot(vs[:, j]))*vs[:, j]
    # normalize
    for i in range(num_vectors):
        vs[:, i] /= np.linalg.norm(vs[:, i])
    return vs

def qr(A):
    # A = S_id_B
    Q = gram_schmidt(A) # = S_id_B'
    # dabei ist die basiswechselmatrix von B nach B' eine obere dreiecksmatrix und damit auch die
    # von B' nach B
    #             Q          R
    #             |          |
    #             V          V
    # Also A = S_id_B' * B'_id_B
    #          ~~~~~~
    #          Gramschmidt
    # => A = Q*R => Q^-1*A = R => (da Q orthogonal) Q'*A = R
    R = Q.transpose().dot(A)
    return Q, R

A =  np.array([[1,2.],[3,4]])
Q, R = qr(A)

print("A:\n", A, "\nQ:\n", Q, "\nR:\n", R, "\nQ*R:\n", Q.dot(R))


import numpy as np
import scipy.special as sp
import math
from NMLA import NMLA

## Test

# parameters
x0, y0 = 0.0, 0.0              # observation point
c0 = 1.0                     # wavespeed at observation point
omega = 1000.0               # frequency
Rest = 3.0                   # estimate of the distance from source to oberservation point

# Add source
xs, ys = 2, 2
rxy = lambda x, y: np.sqrt((x-xs)**2 + (y-ys)**2)
u = lambda x, y, omega: 1j/4*np.sqrt(omega)*sp.hankel1(0, omega*rxy(x,y))
ux = lambda x, y, omega: -1j/4*(omega**1.5)*sp.hankel1(1,omega*rxy(x,y))*(x-xs)/rxy(x,y)
uy = lambda x, y, omega: -1j/4*(omega**1.5)*sp.hankel1(1,omega*rxy(x,y))*(y-ys)/rxy(x,y)

# numerical and exact ray direction
est_ang = NMLA(x0,y0,c0,omega,Rest,u,ux,uy)
ex_ang = math.atan2(y0-ys,x0-xs) + 2*np.pi

# print result
print '\nThe exact ray direction:', ex_ang/np.pi, r'$\pi$', '\n'
print 'The ray direction estimated ny NMLA:', est_ang/np.pi, r'$\pi$', '\n'
print 'Relative error:', abs(est_ang - ex_ang)/abs(ex_ang)

# Compared to MPM, NMLA is more stable, it allows much more noisy level to the source, but MPM is very sensitive to the noise.


import numpy as np
import pandas as pd
import os
import matplotlib.pyplot as plt
import scipy.stats as st
from scipy.stats import ttest_ind, ttest_ind_from_stats

# Read the csv file
if os.path.exists("Georgiapeaches.csv"):
  georgia = pd.read_csv("Georgiapeaches.csv")
if os.path.exists("Yangshanpeaches.csv"):
  yangshan = pd.read_csv("Yangshanpeaches.csv")

# Prepare data
x = georgia['Yield per investment (in kilograms per Martian dollar)'].to_numpy()
y = yangshan['Yield per investment (in kilograms per Martian dollar)'].to_numpy()

mean_x = np.mean(x)
mean_y = np.mean(y)

sdx = np.std(x)
sdy = np.std(y)

n1 = x.size
n2 = y.size

#this is a helper variable to make the calculation cleaner
i = (np.square(sdx) / n1) + (np.square(sdy) / n2)

#calculating the test statistic

z = (mean_x - mean_y) / np.sqrt(i)
print (z)

# 90%
ci_x1 = st.t.interval(0.90, n1-1, loc=mean_x, scale=st.sem(x))
ci_y1 = st.t.interval(0.90, n2-1, loc=mean_y, scale=st.sem(y))
print ("The 90% confidence interval for Georgian peaches:", ci_x1)
print ("The 90% confidence interval for Yangshan peaches:", ci_y1)

# 95%
ci_x2 = st.t.interval(0.95, n1-1, loc=mean_x, scale=st.sem(x))
ci_y2 = st.t.interval(0.95, n2-1, loc=mean_y, scale=st.sem(y))
print ("The 95% confidence interval for Georgian peaches:", ci_x2)
print ("The 95% confidence interval for Yangshan peaches:", ci_y2)

# 99%
ci_x3 = st.t.interval(0.99, n1-1, loc=mean_x, scale=st.sem(x))
ci_y3 = st.t.interval(0.99, n2-1, loc=mean_y, scale=st.sem(y))
print ("The 99% confidence interval for Georgian peaches:", ci_x3)
print ("The 99% confidence interval for Yangshan peaches:", ci_y3)


import numpy as np

class MSE:
    @staticmethod
    def compute(a, y):
        y = y.reshape(1, -1)
        assert(a.shape == y.shape)
        m = a.shape[1]
        return np.sum((a - y) ** 2) / m

    @staticmethod
    def differentiate(a, y):
        return 2 * (a - y)


from sympy import ( symbols, solve, diff, integrate, exp, lambdify, pprint )
import matplotlib.pyplot as plt
import numpy as np

# The life (in months) of a certain electronic computer part has a probability density function defined by F,
# Find the probability that a randomly selected component will last the following lengths of time.

x = symbols( 'x' )
F = .5 * exp( -x / 2 )

# What does the life-span look like?
g_xlim = [ 1, 20 ]
g_ylim = [ -5, 15 ]

lam_p = lambdify( x, F, np )
x_vals = np.linspace( g_xlim[0], g_xlim[1], 1000, endpoint=True )
y_vals = lam_p( x_vals )
plt.plot( x_vals, y_vals )

# Probability it will last 8 months?

a, b = 4, 8
bounds = np.arange( a, b, 1/50., dtype=float)

for n in bounds:
	y = F.subs( { x: n } )
	plt.vlines( x = n, ymin = 0, ymax = y, color = 'Teal', zorder = 1, alpha = .4 )

area = integrate( F, ( x, a, b ) ).evalf()

total_area = integrate( F, ( x, 0, 100 ) ).evalf()

area_pct = round( ( area / total_area ), 4 )
plt.text( 2 , .1, 'Area: {0}%'.format( area_pct ) )

plt.show()

# Find the cumulative distribution function for this random variable.
a, b = 0, x
cdf = integrate( F, ( x, a, b ) )

pprint( cdf )

#  Use the answer to part C to find the probability that a randomly selected component will last at most 6 months.

ans = cdf.subs( { x: 6 } ).evalf()
round( ans, 4 )


import numpy as np

def domainwall_analytic_solution(A, K, d, n_points):
    """
    Computes Neel domain wall magnetisation x component
    in absence of an external magnetic field.
    """
    x_array = np.linspace(0, d, n_points)
    mx_analytic = -np.tanh((x_array - d / 2.) / np.sqrt(A / K))

    return mx_analytic