"""
Author: Peratham Wiriyathammabhum

"""
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# import scipy.sparse.linalg as linalg
from numpy import linalg as LA

def fast_ica(Xin, n_components=3):
	"""
	Perform Fast Independent Component Analysis (FastICA) on an input row matrix X.
	X = AS, where A is a mixing matrix and S are signal sources.

	See: IJCNN'99 Independent Component Analysis: A Tutorial by Aapo Hyvrinen and Erkki Oja
		http://www.cs.jhu.edu/~ayuille/courses/Stat161-261-Spring14/HyvO00-icatut.pdf
	"""
	X = Xin.copy() # for safety
	ni, nd = X.shape

	"""
	Note: This X is a row matrix which is different to the original formulas which assume a column matrix.
	"""
	# centering
	X = (X - np.mean(X, axis=0))

	# whitening makes mixing matrix orthogonal
	D, E = LA.eig(np.cov(X.T))
	ind = np.argsort(-D, axis=0) # sorting descending
	D = D[ind]
	E = E[:, ind]
	D = np.power(D, -0.5)
	D = np.diag(D)
	X = E.dot(D).dot(E.T).dot(X.T)
	X = X.T

	# f, g, g' https://en.wikipedia.org/wiki/FastICA
	f = lambda x: np.log(np.cosh(x))
	g = lambda x: np.tanh(x)
	g_prime = lambda x: 1. - np.power(np.tanh(x), 2)

	W = []
	ones_m = np.ones((ni, 1))
	for i in range(n_components):
		print('[Info] Computing component {}...'.format(i))
		w_p = weight_init(nd, init_mode='random')
		w_p = w_p / np.linalg.norm(w_p, ord=2)

		TERMINATE = False
		while not TERMINATE:
			w_old = w_p.copy()
			first_term = (X.T.dot(g(X.dot(w_p))) / ni)
			second_term = ( g_prime(X.dot(w_p)).T.dot(ones_m) * (w_p) / ni)
			w_p = first_term - second_term
			if (len(W) > 0):
				sum_wp = np.zeros((nd, 1))
				for w_j in W:
					sum_wp += w_p.T.dot(w_j) * (w_j)
				w_p = w_p - sum_wp
			w_p = w_p / np.linalg.norm(w_p, ord=2)
			TERMINATE = not check_diff(w_p, w_old)
		W.append(w_p)
	W = np.asarray(W)
	W = W.squeeze()

	S = X.dot(W)
	return W, S

def check_diff(w_p, w_old, threshold=0.999):
	IS_DIFF = True
	cond = w_p.T.dot(w_old)
	print(cond)
	if cond > threshold:
		IS_DIFF = False
	return IS_DIFF

def weight_init(nd, init_mode='random'):
	if init_mode == 'random':
		theta = np.random.randn(nd, 1)
	elif init_mode=='xavier':
		"""
		Glorot, Xavier, and Yoshua Bengio.
		"Understanding the difficulty of training deep feedforward neural networks."
		Proceedings of the thirteenth international conference on artificial
		intelligence and statistics. 2010.
		"""
		pass
	else:
		pass
	return theta

def main():
	# generate data https://scikit-learn.org/stable/auto_examples/decomposition/plot_ica_blind_source_separation.html
	np.random.seed(0)
	n_samples = 2000
	from scipy import signal
	time = np.linspace(0, 8, n_samples)

	s1 = np.sin(2 * time)  # Signal 1 : sinusoidal signal
	s2 = np.sign(np.sin(3 * time))  # Signal 2 : square signal
	s3 = signal.sawtooth(2 * np.pi * time)  # Signal 3: saw tooth signal

	S = np.c_[s1, s2, s3]
	S += 0.2 * np.random.normal(size=S.shape)  # Add noise

	S /= S.std(axis=0)  # Standardize data
	# Mix data
	A = np.array([[1, 1, 1], [0.5, 2, 1.0], [1.5, 1.0, 2.0]])  # Mixing matrix
	X = np.dot(S, A.T)  # Generate observations

	# timer
	from time import time
	t0 = time()
	# signal source separation
	W, S_ = fast_ica(X)
	t1 = time()
	print('[Info] Fast ICA done in {:.2g} sec.'.format(t1 - t0))

	# plot
	plt.figure()

	models = [X, S, S_]
	names = ['Observations (mixed signal)',
			 'True Sources',
			 'ICA recovered signals']
	colors = ['red', 'steelblue', 'orange']

	for ii, (model, name) in enumerate(zip(models, names), 1):
		plt.subplot(3, 1, ii)
		plt.title(name)
		for sig, color in zip(model.T, colors):
			plt.plot(sig, color=color)

	plt.tight_layout()
	plt.show()
	input("Press Enter to continue...")

	return

if __name__ == '__main__':
	main()

import numpy,from numpy,import scipy,from scipy


import numpy as np

rs = np.random.RandomState(1234)
p = 2
n = 200
py1 = 0.6
mean1 = np.r_[1,1.]
mean0 = -mean1

Y = (rs.rand(n) > py1).astype(int)
X = np.zeros((n,p))
X[Y==0] = rs.multivariate_normal(mean0, np.eye(p), size=(Y==0).sum())
X[Y==1] = rs.multivariate_normal(mean1, np.eye(p), size=(Y==1).sum())

import matplotlib.pyplot as plt
plt.plot(X[Y==0,0], X[Y==0,1], 'ob', label='Class 0')
plt.plot(X[Y==1,0], X[Y==1,1], 'sr', label='Class 1')
plt.legend(loc=2, numpoints=1)

plt.show()

def gradient_ascent(w, b, lamb, eta, n_iters):
    # G is P(Y=1|X) under the current parameters.
    G = 1 / (1. + np.exp(-b-np.dot(X,w)))
    # loss is the function we're maximizing
    loss = -lamb * (w**2).sum() + np.log(G[Y==1]).sum() + np.log(1-G[Y==0]).sum()
    print "iteration:", 0, "| loss:", loss, "| accuracy:", ((G>0.5) == Y).mean()

    for iter in range(1, n_iters+1):
        G = 1 / (1. + np.exp(-b-np.dot(X,w)))
        loss = -lamb * 0.5 * (w**2).sum() + np.log(G[Y==1]).sum() + np.log(1-G[Y==0]).sum()
        print "iteration:", iter, "| loss:", loss, "| accuracy:", ((G>0.5) == Y).mean()

        # Now, do gradient ascent.
        ymg    = Y-G
        grad_b = ymg.sum()
        grad_w = -lamb * w + np.dot(ymg,X)

        b += eta*grad_b
        w += eta*grad_w
    return w,b

init_w = rs.randn(X.shape[1])
init_b = rs.rand()*50-25

w,b=gradient_ascent(w=init_w.copy(), b=init_b, lamb=0., eta=0.01, n_iters=10)

print "\n"

print "Parameters found ... w:", w, "b:", b

# Generate some new testing data
Y_ = (rs.rand(n) > py1).astype(int)
X_ = np.zeros((n,p))
X_[Y_==0] = rs.multivariate_normal(mean0, np.eye(p), size=(Y_==0).sum())
X_[Y_==1] = rs.multivariate_normal(mean1, np.eye(p), size=(Y_==1).sum())

G = 1 / (1. + np.exp(-b-np.dot(X_,w)))

print "\n"

print "Accuracy on test data:", ((G>0.5) == Y_).mean()

x,y = np.mgrid[-4:4:61j,-4:4:61j]
xy = np.c_[ x.flatten(), y.flatten() ]

G = 1 / (1. + np.exp(-b-np.dot(xy,w)))

fig = plt.figure()
# This is a color coding of the numerical prediction over the region.
plt.contourf(x, y, G.reshape(x.shape), cmap=plt.cm.bwr, alpha=0.6)

x1 = (-b-4*w[1]) / w[0]
x2 = (-b+4*w[1]) / w[0]
# This draws the decision boundary.
plt.plot( [x1,x2], [4, -4.], '-k', lw=3)

plt.plot(X[Y==0,0], X[Y==0,1], 'ob')
plt.plot(X[Y==1,0], X[Y==1,1], 'sr')

plt.show()


"""
Principal-component analysis class.

"""
import numpy as np
import pickle
import os

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

class PCA:
    def __init__(self):
        self.W = None
        self.b = None

    def analyze(self, data):
        print("PCA: began analysis")
        covar = np.cov(data, rowvar=False)
        eigvals, eigvecs = np.linalg.eigh(covar)
        self.W = eigvecs[:, ::-1]
        self.b = np.mean(data, axis=0)
        print("PCA: finished analysis")
        return eigvals[::-1]

    def compress(self, data, dimensionality):
        assert self.W is not None
        return (data - self.b).dot(self.W[:, :dimensionality])

    def decompress(self, data):
        assert self.W is not None
        data = np.atleast_2d(data)
        if data.shape[1] < self.W.shape[1]:
            data = np.column_stack((data, np.zeros((len(data), self.W.shape[1]-data.shape[1]), dtype=float)))
        return data.dot(self.W.T) + self.b

    def save(self, filename):
        if filename[-4:] != ".pca":
            filename = filename + ".pca"
        with open(filename, 'wb') as file:
            pickle.dump((self.W, self.b), file, pickle.HIGHEST_PROTOCOL)

    def load(self, filename):
        if filename[-4:] != ".pca":
            filename = filename + ".pca"
        with open(filename, 'rb') as file:
            self.W, self.b = pickle.load(file)

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

if __name__ == "__main__":
    print("PCA: began unit-test")

    import seaborn
    seaborn.set()
    from matplotlib import pyplot

    filename = os.path.join(os.path.dirname(__file__), 'datasets', 'IRIS.csv')

    features = np.genfromtxt(fname=filename,
                             dtype=float,
                             comments='#',
                             delimiter=',',
                             skip_header=1,
                             usecols=(0, 1, 2, 3))
    labels = np.genfromtxt(fname=filename,
                           dtype=str,
                           comments='#',
                           delimiter=',',
                           skip_header=1,
                           usecols=(4))

    pca = PCA()
    pca.analyze(features)
    features_compressed = pca.compress(features, 2)

    should_be_features = pca.decompress(pca.compress(features, 4))
    print("PCA: methods compress and decompress are inverses? {0}".format(np.allclose(features, should_be_features)))

    fig = pyplot.figure()
    ax = fig.add_subplot(1, 1, 1)
    ax.set_title('KDE of the Iris Data-Set', fontsize=16)

    ax.set_xlim([-4.0, 4.0])
    ax.set_xlabel("PCA Component 0", fontsize=12)
    ax.set_ylim([-1.5, 1.5])
    ax.set_ylabel("PCA Component 1", fontsize=12)

    seaborn.kdeplot(features_compressed[:50, 0], features_compressed[:50, 1], cmap="Greens", shade=True, shade_lowest=False)
    seaborn.kdeplot(features_compressed[50:100, 0], features_compressed[50:100, 1], cmap="Reds", shade=True, shade_lowest=False)
    seaborn.kdeplot(features_compressed[100:, 0], features_compressed[100:, 1], cmap="Blues", shade=True, shade_lowest=False)
    ax.text(1.2, 1.2, "setosa", size=16, color=seaborn.color_palette("Greens")[-2])
    ax.text(-0.5, 0.7, "versicolor", size=16, color=seaborn.color_palette("Reds")[-2])
    ax.text(-3.5, 0.9, "virginica", size=16, color=seaborn.color_palette("Blues")[-2])

    print("PCA: finished unit-test")
    pyplot.show()


import numpy as np
from scipy import stats
from sklearn.metrics import confusion_matrix, f1_score

y1_neg = np.array([0.6, 0.1, 0.2, 0.1])
y1_pos = np.array([0.3, -0.1, -0.3, 0.2, 0.4, -0.2])
y2_neg = np.array(["A", "B", "A", "C"])
y2_pos = np.array(["B", "C", "C", "B", "A", "C"])
y3_neg = np.array([0.2, -0.1, -0.1, 0.8])
y3_pos = np.array([0.1, 0.2, -0.1, 0.5, -0.4, 0.4])
y4_neg = np.array([0.4, -0.4, 0.2, 0.8])
y4_pos = np.array([0.3, -0.2, 0.2, 0.6, -0.7, 0.3])

p_neg = 0.4
p_pos = 0.6

miu_y1_neg = np.mean(y1_neg) #0.24999999999999997
miu_y1_pos = np.mean(y1_pos) #0.049999999999999996

cov_y1_neg = np.cov(y1_neg) #0.05666666666666665
cov_y1_pos = np.cov(y1_pos) #0.08300000000000002

mode_y2_neg = stats.mode(y2_neg)[0][0] #A
mode_y2_pos = stats.mode(y2_pos)[0][0] #C

miu_y34_neg = np.array([np.mean(y3_neg), np.mean(y4_neg)]) #[0.2  0.25]
miu_y34_pos = np.array([np.mean(y3_pos), np.mean(y4_pos)]) #[0.11666667 0.08333333]

cov_y34_neg = np.cov([y3_neg, y4_neg])  #[[0.18 0.18] [0.18 0.25]]
cov_y34_pos = np.cov([y3_pos, y4_pos])  #[[0.10966667 0.12233333] [0.12233333 0.21366667]]

inv_cov_y34_neg = np.linalg.inv(np.cov([y3_neg, y4_neg])) #[[ 19.84126984 -14.28571429] [-14.28571429  14.28571429]]
inv_cov_y34_pos = np.linalg.inv(np.cov([y3_pos, y4_pos])) #[[ 25.23622047 -14.4488189 ] [-14.4488189   12.95275591]]

det_cov_y34_neg = np.linalg.det(np.cov([y3_neg, y4_neg])) #0.0126
det_cov_y34_pos = np.linalg.det(np.cov([y3_pos, y4_pos])) #0.008466666666666664

# P(c|y1,y2,y3,y4) = P(c)P(y1,y2,y3,y4|c)/P(y1,y2,y3,y4) = P(c)P(y1|c)P(y2|c)P(y3,y4|c)/P(y1,y2,y3,y4)

# P(y1,y2,y3,y4) = P(y1,y2,y3,y4 e c=0) + P(y1,y2,y3,y4 e c=1)
# P(y1,y2,y3,y4 e c) = P(c)P(y1,y2,y3,y4|c) = P(c)P(y1|c)P(y2|c)P(y3,y4|c)
def pred_c(
    x: np.array,
    p_pos, p_neg,
    y2_pos, y2_neg,
    miu_uni_pos, miu_uni_neg,
    cov_uni_pos, cov_uni_neg,
    miu_bi_pos, miu_bi_neg,
    cov_bi_pos, cov_bi_neg
    ):
    # P(c)P(y1|c)P(y2|c)P(y3,y4|c)
    prob_num_pos = prob(x, p_pos, y2_pos, miu_uni_pos, cov_uni_pos, miu_bi_pos, cov_bi_pos)
    prob_num_neg = prob(x, p_neg, y2_neg, miu_uni_neg, cov_uni_neg, miu_bi_neg, cov_bi_neg)
    #print(f"x|c=0: {prob_num_neg}")
    #print(f"x|c=1: {prob_num_pos}")

    # P(y1,y2,y3,y4) = P(y1,y2,y3,y4 e c=0) + P(y1,y2,y3,y4 e c=1)
    prob_den = prob_num_pos + prob_num_neg

    result = 1 if prob_num_pos > prob_num_neg else 0
    return prob_num_pos/prob_den, result

# P(c)P(y1|c)P(y2|c)P(y3,y4|c)
def prob(x: np.array, p_c, y2_c, miu_uni, cov_uni, miu_bi, cov_bi):

    p_y1 = prob_y1(x[0],miu_uni,cov_uni)
    p_y2 = prob_y2(x[1],y2_c)
    p_y3y4 = prob_y3y4(x,2,miu_bi,cov_bi)

    return p_c*p_y1*p_y2*p_y3y4

def prob_y1(x, miu, cov):
    return univariate_normal(x,miu,cov)

def prob_y2(x,y):
    """probability of x in y set"""
    total = 0
    for i in range(len(y)):
        if x == y[i]:
            total += 1
    return total/len(y)

def prob_y3y4(x,d,miu,cov):
    return multivariate_normal(np.array([x[2],x[3]]), d, miu, cov)

def univariate_normal(x, mean, variance):
    """pdf of the univariate normal distribution."""
    return ((1. / np.sqrt(2 * np.pi * variance)) *
            np.exp(-(x - mean)**2 / (2 * variance)))

def multivariate_normal(x: np.array, d, mean: np.array, covariance):
    """pdf of the multivariate normal distribution."""
    x_m = x - mean
    return (1. / (np.sqrt((2 * np.pi)**d * np.linalg.det(covariance))) *
            np.exp(-(np.linalg.solve(covariance, x_m).T.dot(x_m)) / 2))

def print_confusion_matrix(true,pred):
    tn, fp, fn, tp = confusion_matrix(true,pred).ravel()
    print("TN: " + str(tn))
    print("FN: " + str(fn))
    print("TP: " + str(tp))
    print("FP: " + str(fp))
    return tn, fp, fn, tp

def find_accuracies(probs_pos, x_c):

    def predict(prob_pos, threshold):
        return 1 if prob_pos > threshold else 0 #Should we use > or >=? Two different optimal thresholds will be returned that way

    size = len(probs_pos)

    # accuracy for each threshold
    accuracies = []
    best_accuracy = 0

    for i in range(size):
        x_pred = []
        for j in range(size):
            x_pred.append(predict(probs_pos[j], probs_pos[i])) #Find prediction of probs_pos[j] using probs_pos[i] as threshold
        tn, fp, fn, tp = confusion_matrix(x_c,x_pred).ravel()
        accuracy = (tn+tp)/size
        accuracies.append(accuracy)
        if accuracy > best_accuracy:
            best_accuracy = accuracy
            best_threshold = probs_pos[i]
    print(f"Accuracies: {accuracies}")
    print(f"Best threshold: {best_threshold}")

if __name__ == "__main__":

    y1 = [0.6, 0.1, 0.2, 0.1,0.3, -0.1, -0.3, 0.2, 0.4, -0.2]
    y2 = ["A", "B", "A", "C","B", "C", "C", "B", "A", "C"]
    y3 = [0.2, -0.1, -0.1, 0.8,0.1, 0.2, -0.1, 0.5, -0.4, 0.4]
    y4 = [0.4, -0.4, 0.2, 0.8,0.3, -0.2, 0.2, 0.6, -0.7, 0.3]

    x_c = [0,0,0,0,1,1,1,1,1,1]
    x_pred = []

    # probability of P(c=1|x)
    probs_pos = []
    probs_neg = []

    for i in range(10):
        x = [y1[i],y2[i],y3[i],y4[i]]
        prob_pos, result = pred_c(
                    x,
                    p_pos,p_neg,
                    y2_pos, y2_neg,
                    miu_y1_pos, miu_y1_neg,
                    cov_y1_pos, cov_y1_neg,
                    miu_y34_pos, miu_y34_neg,
                    cov_y34_pos, cov_y34_neg
                )
        x_pred.append(result)
        probs_pos.append(prob_pos)

    tn, fp, fn, tp = print_confusion_matrix(x_c,x_pred)
    print("F1 Score: " + str(f1_score(x_c, x_pred)))
    print("P(c=1|x) for each x")
    print(probs_pos)
    find_accuracies(probs_pos, x_c)


# Rotating Calipers Algorithms (A.K.A Shamos Algorithm) use to find the diameter of contour
# This algorithm appeared in book (p178-p181) "Shamos, Franco P. Preparata, Michael Ian (1985). Computational Geometry An Introduction"
import cv2
import numpy as np
import math

def area(cnt, i, j, k):
    return cv2.contourArea(np.array([cnt[i], cnt[j], cnt[k]]))

def next_point(cnt, i):
    return (i + 1) % len(cnt)

def distance(p1, p2):
    return math.sqrt((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2)

def get_all_antipodal_pairs(cnt):
    p0 = 0
    p = len(cnt) - 1
    q = next_point(cnt, p)
    while area(cnt, p, next_point(cnt, p), next_point(cnt, q)) > area(cnt, p, next_point(cnt, p), q):
        q = next_point(cnt, q)

    q0 = q

    while q != p0:
        p = next_point(cnt, p)
        yield p, q

        while area(cnt, p, next_point(cnt, p), next_point(cnt, q)) > area(cnt, p, next_point(cnt, p), q):
            q = next_point(cnt, q)
            if (p, q) != (q0, p0):
                yield p, q
            else:
                break

        if area(cnt, p, next_point(cnt, p), next_point(cnt, q)) == area(cnt, p, next_point(cnt, p), q):
            if (p, q) != (q0, len(cnt) - 1):
                yield p, next_point(cnt, q)
            else:
                break

def get_diameter(cnt):
    diameter = -1.0
    start = None
    end = None

    for i, j in get_all_antipodal_pairs(cnt):
        dist = distance(cnt[i][0], cnt[j][0])
        if dist > diameter:
            diameter = dist
            start = cnt[i][0]
            end = cnt[j][0]

    return diameter, start, end

if __name__ == '__main__':
    cnt = np.array(
        [
            [[10, 6]],
            [[9, 7]],
            [[8, 8]],
            [[7, 9]],
            [[7, 10]],
            [[7, 11]],
            [[7, 12]],
            [[7, 13]],
            [[8, 14]],
            [[8, 15]],
            [[8, 16]],
            [[9, 17]],
            [[10, 17]],
            [[11, 17]],
            [[11, 16]],
            [[12, 15]],
            [[13, 15]],
            [[14, 14]],
            [[15, 14]],
            [[15, 13]],
            [[16, 12]],
            [[16, 11]],
            [[15, 11]],
            [[14, 10]],
            [[14, 9]],
            [[13, 8]],
            [[13, 7]],
            [[12, 6]],
            [[11, 6]],
        ]
    )

    hull = cv2.convexHull(cnt, clockwise=False)

    diameter, start, end = get_diameter(hull)

    print(f"diameter: {diameter} start: {start} end: {end}")


# -*- coding:utf-8 -*-
__version__ = '0.0.1'
__author__ = 'Dr. Yingfeng, Yu'
from scipy import stats
from math import log, sqrt, exp

class call_option:
    def __init__(self, S0, K, T, t, r, sigma):
        self.S0 = float(S0)
        self.K  = K
        self.T  = T
        self.t  = t
        self.r  = r
        self.sigma = sigma
        self.d1 = (log(S0/K)+(r+0.5*sigma**2)*(T-t))/(sigma*sqrt((T-t)))
        self.d2 = (log(S0/K)+(r-0.5*sigma**2)*(T-t))/(sigma*sqrt((T-t)))

    def __del__(self):
        class_name =self.__class__.__name__
        print(class_name, ':delete our call_option obj')

    def val(self):
        val=(self.S0*stats.norm.cdf(self.d1, 0.0, 1.0)-self.K*exp(-self.r*(self.T-self.t))*stats.norm.cdf(self.d2, 0.0, 1.0))
        return val

    def delta(self):
        delta=stats.norm.cdf(self.d1, 0.0, 1.0)
        return delta

    def gamma(self):
        gamma=stats.norm.pdf(self.d1, 0.0, 1.0)/(self.S0*self.sigma*sqrt(self.T-self.t))
        return gamma

    def theta(self,gamma):
        theta = -self.r*self.K*(sqrt(self.T-self.t))*stats.norm.cdf(self.d2)-0.5*gamma*(self.S0*self.sigma)*(self.S0*self.sigma)
        return theta

    def kappa(self):
        kappa= (stats.norm.cdf(-self.d2)-1.00)*exp(-self.r*(self.T-self.r))
        return kappa

    def rho(self):
        rho=self.K*(self.T-self.t)*stats.norm.cdf(self.d2)*exp(-self.r*(self.T-self.t))
        return rho

    def vega(self):
        vega = self.K * stats.norm.cdf(self.d1, 0.0, 1.0) * sqrt(self.T - self.t)
        return vega

    def impvol(self, C0, sigma_est= 0.2, N= 1000):
        opts = call_option(self.S0, self.K, self.T, self.t, self.r, sigma_est)
        for i in range(N):
            opts.sigma =opts.sigma-(opts.val()-C0)/opts.vega()
        return opts.sigma

    def prt_option_info(self):
        call_price=call_option(self.S0, self.K, self.T, self.t, self.r, self.sigma)
        value=call_price.val()
        veg=call_price.vega()
        delt=call_price.delta()
        gam=call_price.gamma()
        thet=call_price.theta(gam)
        kapp=call_price.kappa()
        rh=call_price.rho()
        iv=call_price.impvol(C0=value)
        print('When we assume \nS0=%f K=%f r=%f sigma=%f' %(self.S0, self.K, self.r, self.sigma))
        print('The length T\t=%f and the start time t\t=%f' %(self.T,self.t))
        print('The price of call option \t=\t %f' %value)
        print ('==============The Greek info================')
        print('The Delta of call option \t=\t %f' % delt)
        print('The Gamma of call option \t=\t %f' % gam)
        print('The Theta of call option \t=\t %f' % thet)
        print('The Kappa of call option \t=\t %f' % kapp)
        print('The Rho of call option \t\t=\t %f' % rh)
        print('The Vega of call option \t=\t %f' %veg)
        print('The implied volatility \t\t=\t %f' %iv)
        #return


from __future__ import print_function

import numpy as np
import matplotlib.pyplot as plt

# For reproducibility
np.random.seed(1000)

nb_samples = 1000

def zero_center(X):
    return X - np.mean(X, axis=0)

def whiten(X, correct=True):
    Xc = zero_center(X)
    _, L, V = np.linalg.svd(Xc)
    W = np.dot(V.T, np.diag(1.0 / L))
    return np.dot(Xc, W) * np.sqrt(X.shape[0]) if correct else 1.0

if __name__ == '__main__':
    # Create the dataset
    X = np.random.normal(0.0, [2.5, 1.0], size=(nb_samples, 2))

    theta = np.pi / 4.0
    R = np.array([[np.cos(theta), -np.sin(theta)], [np.sin(theta), np.cos(theta)]])

    Xr = np.dot(X, R)

    # Create a whitened version
    Xw = whiten(Xr)

    # Print the whitened covariance matrix
    print(np.cov(Xw.T))

    # Show original and whitened datasets
    fig, ax = plt.subplots(1, 2, figsize=(15, 5))

    ax[0].scatter(Xr[:, 0], Xr[:, 1])
    ax[0].set_xticks(np.arange(-10, 10), 2)
    ax[0].set_yticks(np.arange(-8, 8), 2)
    ax[0].set_xlabel(r'$x_1$')
    ax[0].set_ylabel(r'$x_2$')
    ax[0].set_title(r'Original dataset')
    ax[0].grid()

    ax[1].scatter(Xw[:, 0], Xw[:, 1])
    ax[1].set_xticks(np.arange(-10, 10), 2)
    ax[1].set_yticks(np.arange(-8, 8), 2)
    ax[1].set_xlabel(r'$x_1$')
    ax[1].set_ylabel(r'$x_2$')
    ax[1].set_title(r'Whitened dataset')
    ax[1].grid()

    plt.show()


import numpy as np

x = np.array([[1,2],[3,4]], dtype=np.float64)
y = np.array([[5,6],[7,8]], dtype=np.float64)

# Elementwise sum; both produce the array
# [[ 6.0  8.0]
#  [10.0 12.0]]
print(x + y)
print(np.add(x, y))

# Elementwise difference; both produce the array
# [[-4.0 -4.0]
#  [-4.0 -4.0]]
print(x - y)
print(np.subtract(x, y))

# Elementwise product; both produce the array
# [[ 5.0 12.0]
#  [21.0 32.0]]
print(x * y)
print(np.multiply(x, y))

# Elementwise division; both produce the array
# [[ 0.2         0.33333333]
#  [ 0.42857143  0.5       ]]
print(x / y)
print(np.divide(x, y))

# Elementwise square root; produces the array
# [[ 1.          1.41421356]
#  [ 1.73205081  2.        ]]
print(np.sqrt(x))

v = np.array([9, 10])
w = np.array([11, 12])

print(v.dot(w))
print(np.dot(v, w))

print(x.dot(y))
print(np.dot(x, y))

x = np.array([[1,2], [3,4]])
print(x)    # Prints "[[1 2]
            #          [3 4]]"
print(x.T)  # Prints "[[1 3]
            #          [2 4]]"

# Note that taking the transpose of a rank 1 array does nothing:
v = np.array([1,2,3])
print(v)    # Prints "[1 2 3]"
print(v.T)  # Prints "[1 2 3]"


"""
Simple Metropolis Hastings sampler taken from Hogg and Foreman-MacKey(2018):

  From Problem 2:
  Sample in a single parameter x and give the sampler
  as its density function p(x) a Gaussian density with
  mean 2 and variance 2. Make the proposal distribution
  q (x'∣x ) a Gaussian pdf for x′ with mean x and
  variance 1. Initialize the sampler with x = 0 and run
  the sampler for more than 10000 steps. Plot the results
  as a histogram with the true density overplotted sensibly.

  Redo Problem 2, but now with an input density that is a
  function of two variables (x, y). For the density function use
  two different functions. (a) The first density function is a
  covariant two-dimensional Gaussian density with variance
  tensor: V = [[2.0, 1.2], [1.2, 2.0]] ... For the proposal
  distribution q (x',y'∣x, y) use a two-dimensional Gaussian
  density with mean at [x, y] and variance tensor set to the
  two-dimensional identity matrix.

"""

import probayes as pb
import numpy as np
import scipy.stats
from pylab import *; ion()

n_steps = 12288
prop_stdv = np.sqrt(1)

def q(**kwds):
  x, xprime = kwds['x'], kwds["x'"]
  y, yprime = kwds['y'], kwds["y'"]
  return scipy.stats.norm.pdf(yprime, loc=y, scale=prop_stdv) * \
         scipy.stats.norm.pdf(xprime, loc=x, scale=prop_stdv)

x = pb.RV('x', vtype=float, vset=(-np.inf, np.inf))
y = pb.RV('y', vtype=float, vset=(-np.inf, np.inf))
process = pb.SP(x & y)
process.set_prob(scipy.stats.multivariate_normal, [0., 0.],
                 [[2.0, 1.2], [1.2, 2.0]])
process.set_tran(q)
lambda_delta = lambda : process.Delta(x=scipy.stats.norm.rvs(loc=0., scale=prop_stdv),
                                      y=scipy.stats.norm.rvs(loc=0., scale=prop_stdv))
process.set_delta(lambda_delta)
process.set_scores('hastings')
process.set_update('metropolis')
sampler = process.sampler({'x': 0., 'y': 1.}, stop=n_steps)
samples = [sample for sample in sampler]
summary = process(samples)
n_accept = summary.u.count(True)
inference = summary.v.rescaled()
xvals, yvals, post = inference['x'], inference['y'], inference.prob

# PLOT DATA
figure()
subplot(2, 2, 1)
c_norm = Normalize(vmin=np.min(post), vmax=np.max(post))
c_map = cm.jet(c_norm(post))
plot(xvals, yvals, '-', color=(0.7, 0.7, 0.7, 0.3))
scatter(xvals, yvals, color=c_map, marker='.', alpha=1.)
xlabel(r'$x$')
ylabel(r'$y$')

ax = subplot(2, 2, 2)
ybins = np.linspace(np.min(yvals), np.max(yvals), 128)
yhist, _ = np.histogram(yvals, ybins)
yprop = yhist / (n_steps * (ybins[1]-ybins[0]))
step(ybins[:-1], yprop, 'b')
ax.yaxis.set_label_position('right')
ax.yaxis.tick_right()
xlabel(r'$y$')
ylabel('Relative frequency')

subplot(2, 2, 3)
xbins = np.linspace(np.min(xvals), np.max(xvals), 128)
xhist, _ = np.histogram(xvals, xbins)
xprop = xhist / (n_steps * (xbins[1]-xbins[0]))
step(xbins[:-1], xprop, 'b')
xlabel(r'$x$')
ylabel('Relative frequency')


import numpy as np

# All of these expect two identically sized numpy arrays as inputs
# and return the same size error output.

class Abs(object):
    @staticmethod
    def __str__():
        return "mean absolute error"

    @staticmethod
    def calc(x):
        return np.mean(np.abs(x))

    @staticmethod
    def calc_d(x):
        return np.sign(x)

class Sqr(object):
    @staticmethod
    def __str__():
        return "mean squared error"

    @staticmethod
    def calc(x):
        return np.mean(x**2)

    @staticmethod
    def calc_d(x):
        return 2 * x


## Tanh activation function

import numpy as np

class Tanh:
    def __init__(self):
        """
        ## This function is used to calculate the sigmoid and the derivative
            of a tanh
        """

    def forward(self, x):
        return np.tanh(x)

    def backward(self, x):
        return 1.0 - np.square(x)


# Sampling from an unnormalized Gamma density via MALA

# %% Import packages

import matplotlib.pyplot as plt
import numpy as np
import scipy.stats as stats
import seaborn as sns
import torch

from torch.utils.data import DataLoader

from eeyore.datasets import EmptyXYDataset
from eeyore.models import DistributionModel
from eeyore.samplers import MALA

# %% Set up unnormalized target density

v = torch.tensor([2., 1.], dtype=torch.float64)

def log_pdf(theta, x, y):
    return (v[0] - 1) * theta - torch.exp(theta) / v[1] + theta # Jacobian

model = DistributionModel(log_pdf, 1, dtype=torch.float64)

# %% Setup MALA sampler

sampler = MALA(
    model,
    theta0=torch.tensor([-1], dtype=model.dtype),
    dataloader=DataLoader(EmptyXYDataset()),
    step=0.25
)

# %% Run MALA sampler

sampler.run(num_epochs=11000, num_burnin_epochs=1000)

# %% For convenience, name the chain list

chain_list = sampler.get_chain()

# %% Compute acceptance rate

print('Acceptance rate: {}'.format(chain_list.acceptance_rate()))

# %% Compute Monte Carlo mean

print('Monte Carlo mean: {}'.format(chain_list.mean()))

# %% Compute Monte Carlo standard error

print('Monte Carlo standard error: {}'.format(chain_list.mc_se()))

# %% Plot traces of simulated Markov chain

chain = chain_list.get_param(0)
plt.figure()
sns.lineplot(x=range(len(chain)), y=chain)
plt.xlabel('Iteration')
plt.ylabel('Parameter value')
plt.title(r'Traceplot of $\theta_{{{}}}$'.format(1))

# %% Plot histograms of marginals of simulated Markov chain

x_hist_range = np.linspace(0.001, 10, 100)

plt.figure()
plot = sns.histplot(chain_list.get_param(0).exp(), stat='density', label='Simulated')
plot.set_xlabel('Parameter value')
plot.set_ylabel('Relative frequency')
plot.set_title(r'Traceplot of $\theta_{{{}}}$'.format(1))
sns.lineplot(x=x_hist_range, y=stats.gamma.pdf(x_hist_range, v[0], scale=v[1]), color='red', label='Target')
plot.legend()


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sun Nov  4 13:30:33 2018

@author: Kazuki
"""

import numpy as np
import matplotlib.pyplot as plt
from scipy import signal

N = 64 # データ数
n = np.arange(N)
f1 = 4 # 周期①
f2 = 10 # 周期②
a1 = 1.5 # 振幅①
a2 = 3 # 振幅②
f = a1 * np.sin(f1 * 2 * np.pi * (n/N)) + a2 * np.sin(f2 * 2 * np.pi * (n/N))

# グラフ表示
plt.figure(figsize=(8, 4))
plt.xlabel('n')
plt.ylabel('Signal')
plt.plot(f)

# =============================================================================
#
# =============================================================================
# 高速フーリエ変換(FFT)
F = np.fft.fft(f)
# FFT結果（複素数）を絶対値に変換
F_abs = np.abs(F)
# 振幅を元に信号に揃える
F_abs_amp = F_abs / N * 2 # 交流成分はデータ数で割って2倍する
F_abs_amp[0] = F_abs_amp[0] / 2 # 直流成分（今回は扱わないけど）は2倍不要

# グラフ表示（データ数の半分の周期を表示）
plt.plot(F_abs_amp[:int(N/2)+1])


import numpy as np

def l2_distance(a, b):
    """Computes the Euclidean distance matrix between a and b.

    Inputs:
        A: D x M array.
        B: D x N array.

    Returns:
        E: M x N Euclidean distances between vectors in A and B.

    Author   : Roland Bunschoten
               University of Amsterdam
               Intelligent Autonomous Systems (IAS) group
               Kruislaan 403  1098 SJ Amsterdam
               tel.(+31)20-5257524
               bunschot@wins.uva.nl
    Last Rev : Wed Oct 20 08:58:08 MET DST 1999
    Tested   : PC Matlab v5.2 and Solaris Matlab v5.3

    Copyright notice: You are free to modify, extend and distribute
       this code granted that the author of the original code is
       mentioned as the original author of the code.

    Fixed by JBT (3/18/00) to work for 1-dimensional vectors
    and to warn for imaginary numbers.  Also ensures that
    output is all real, and allows the option of forcing diagonals to
    be zero.

    Basic functionality ported to Python 2.7 by JCS (9/21/2013).
    """

    if a.shape[0] != b.shape[0]:
        raise ValueError("A and B should be of same dimensionality")

    aa = np.sum(a**2, axis=0)
    bb = np.sum(b**2, axis=0)
    ab = np.dot(a.T, b)

    return np.sqrt(aa[:, np.newaxis] + bb[np.newaxis, :] - 2*ab)


import numpy as np
from matplotlib import pyplot as plt

class GamblerProblem:
    def __init__(self, ph, max_capital, threshold):
        self.ph = ph
        self.threshold = threshold
        self.max_capital = max_capital
        self.state_value = np.zeros(max_capital + 1)
        self.optimal_policy = np.zeros(max_capital + 1)
        self.state_value[100] = 1

    def expected_reward(self, curr_state):
        action_state = [0 , min(curr_state, self.max_capital - curr_state)]
        new_state_value = 0
        optimal_next_state = 0
        for i in range(action_state[0], action_state[1]+1):
            dp = self.ph * self.state_value[curr_state + i] + (1 - self.ph) * self.state_value[curr_state - i]
            if(new_state_value < dp):
                new_state_value = dp
                optimal_next_state = i
        return new_state_value, optimal_next_state

    def value_iteration(self):
        iteration_count = 1
        while True:
            delta = 0
            for curr_state in range(1, self.max_capital):
                new_state_value, _ = self.expected_reward(curr_state)
                delta = max(delta, abs(self.state_value[curr_state] - new_state_value))
                self.state_value[curr_state] = new_state_value
            if(iteration_count in [1, 2, 3, 5, 10, 50, 100, 500, 1000]):
                plt.plot(self.state_value, label = 'Sweep '+str(iteration_count))
            print("Value Iteration Count = " + str(iteration_count) + " with delta = " + str(delta))
            iteration_count += 1
            if delta < self.threshold:
                break

    def policy_update(self):
        for curr_state in range(1, self.max_capital):
            _, optimal_next_state = self.expected_reward(curr_state)
            self.optimal_policy[curr_state] = optimal_next_state

    def display_state_value(self):
        plt.plot(self.state_value, label="Final Value Function")
        plt.xlabel('Capital')
        plt.ylabel('Value Estimate')
        plt.title('Value Function')
        plt.legend()
        plt.show()

    def display_optimal_policy(self):
        plt.bar(range(0, self.max_capital+1), self.optimal_policy)
        plt.xlabel('Capital')
        plt.ylabel('Final Policy(Stake')
        plt.title('Final Policy Function')
        plt.show()

# For ph = 0.4, 0.25 the graph isnt very unexpected but something intersting happens at ph=0.55
# Check out yourself
def main(ph = 0.55, max_capital = 100, threshold = 0.000001):
    obj = GamblerProblem(ph, max_capital, threshold)
    obj.value_iteration()
    obj.policy_update()
    obj.display_state_value()
    obj.display_optimal_policy()

if __name__ == '__main__':
    main()


import os
from random import randint
import math
import numpy as np
import matplotlib.font_manager as fm
import matplotlib.pyplot as plt

# gs_font = fm.FontProperties(
#                 fname='/System/Library/Fonts/Supplemental/GillSans.ttc')
thisdir = os.path.dirname(os.path.realpath(__file__))
plt.style.use(os.path.join(thisdir, 'style.mplstyle'))

def generate_birthday():
    """Generate an integer in [1, 365] uniform dist"""
    return randint(1, 365)

def count_until_match():
    birthdays = [generate_birthday()]

    while birthdays[-1] not in birthdays[:-1]:
        birthdays.append(generate_birthday())

    return len(birthdays)

def mc(nsamples=1000):
    return [count_until_match() for _ in range(nsamples)]

def prob_no_match(n):
    """analytical result using integers - python can handle arb large numbers"""
    return math.factorial(n)*math.comb(365,n)/(365**n)

def plot_actual(logy=False, show_match=True, show_no_match=True):
    x = range(1, 366)
    y = [prob_no_match(n) for n in x]
    y2 = [1 - prob_no_match(n) for n in x]

    fig, ax1 = plt.subplots()
    plt.title('Birthday problem')

    if show_no_match:
        ax1.plot(x, y, 'r', lw=2, alpha=0.7, label='no match')
    if show_match:
        ax1.plot(x, y2, 'g', lw=2, alpha=0.7, label='match')
    plt.grid(axis='y', alpha=0.75)

    ax1.set_xlabel('People')
    ax1.set_ylabel('Probability')
    xmax = 100
    ax1.set_xlim(1, xmax)
    ax1.set_ylim(0, 1)
    if logy:
        ax1.set_ylim(1e-150, 10)
        ax1.set_yscale('log')
        ax1.set_xlim(1, 365)
    else:
        n50 = 23
        ax1.axhline(0.5, xmin=n50/xmax, color='k', alpha=0.7, ls='--')
        ax1.axvline(n50, ymax=0.5, color='k', alpha=0.7, ls='--')

    plt.legend()

    return fig, [ax1, ax2]

def plot_mc(x, show_true=False, show_approx=False):
    people = days = np.arange(1, 366)
    xmax = 100

    hist, _ = np.histogram(x, bins=people)
    # these are %
    cumulative = np.cumsum(hist)*100./sum(hist)

    fig, ax1 = plt.subplots()

    n, bins, patches = ax1.hist(x=x, bins=people, color='blue',
                                alpha=0.4, rwidth=0.75, ec='black')
    plt.grid(axis='y', alpha=0.75)

    ax1.set_xlabel('Value')
    ax1.set_ylabel('Count')
    plt.title(f'N={len(x)}')
    ax1.set_xlim(1, xmax)

    maxfreq = n.max()
    ax1.set_ylim(ymax=np.ceil(maxfreq / 10) * 10 if maxfreq % 10 else maxfreq + 10)

    ax2 = ax1.twinx()
    miny2, maxy2 = [0.0, 110.]
    ax2.set_ylim(miny2, maxy2)

    ax2.plot(days[:-1], cumulative, c='green', lw=2, alpha=0.8)
    ax2.set_ylabel('% of people until same birthday')

    def mark_prop_line(pct, colour='red'):
        # index of when we cross pct% chance
        ipeople = next((i for i, c in enumerate(cumulative) if c > pct), -1)
        ax2.axhline(pct, xmin=days[ipeople]/xmax, color=colour, alpha=0.7, ls='--')
        ax2.axvline(days[ipeople], ymax=pct/maxy2, color=colour, alpha=0.7, ls='--')
        plt.text(80, pct+1, f'$p={pct}%$, $\mu={days[ipeople]}$')

    mark_prop_line(50, colour='red')
    mark_prop_line(70, colour='orange')
    mark_prop_line(95, colour='yellow')
    mark_prop_line(99, colour='purple')

    if show_true:
        # using approximation of expontential
        approx = (1 - np.exp(-people*people/(2*365)))*100.
        ax2.plot(days, approx, c='pink', lw=1, alpha=0.3)

    if show_approx:
        # using approximation of expontential
        approx = (1 - np.exp(-people*people/(2*365)))*100.
        ax2.plot(days, approx, c='pink', lw=1, alpha=0.3)

    return fig, [ax1, ax2]

N = 1000
values = mc(nsamples=N)

fig, [ax1, ax2] = plot_mc(values)
fig, [ax1, ax2] = plot_actual()
fig, [ax1, ax2] = plot_actual(logy=True, show_match=False)

plt.show()


# pca 1d : visualize variacnce of projecton
# Code is based on chapter 8 of
# https://github.com/ageron/handson-ml2

import numpy as np
import matplotlib.pyplot as plt

from sklearn.decomposition import PCA

angle = np.pi / 5
stretch = 5
m = 200

np.random.seed(3)
X = np.random.randn(m, 2) / 10
X = X.dot(np.array([[stretch, 0],[0, 1]])) # stretch
X = X.dot([[np.cos(angle), np.sin(angle)], [-np.sin(angle), np.cos(angle)]]) # rotate

u1 = np.array([np.cos(angle), np.sin(angle)])
u2 = np.array([np.cos(angle - 2 * np.pi/6), np.sin(angle - 2 * np.pi/6)])
u3 = np.array([np.cos(angle - np.pi/2), np.sin(angle - np.pi/2)])

X_proj1 = X.dot(u1.reshape(-1, 1))
X_proj2 = X.dot(u2.reshape(-1, 1))
X_proj3 = X.dot(u3.reshape(-1, 1))

plt.figure(figsize=(8,4))
plt.subplot2grid((3,2), (0, 0), rowspan=3)
plt.plot([-1.4, 1.4], [-1.4*u1[1]/u1[0], 1.4*u1[1]/u1[0]], "k-", linewidth=1)
plt.plot([-1.4, 1.4], [-1.4*u2[1]/u2[0], 1.4*u2[1]/u2[0]], "k--", linewidth=1)
plt.plot([-1.4, 1.4], [-1.4*u3[1]/u3[0], 1.4*u3[1]/u3[0]], "k:", linewidth=2)
plt.plot(X[:, 0], X[:, 1], "bo", alpha=0.5)
plt.axis([-1.4, 1.4, -1.4, 1.4])
plt.arrow(0, 0, u1[0], u1[1], head_width=0.1, linewidth=5, length_includes_head=True, head_length=0.1, fc='k', ec='k')
plt.arrow(0, 0, u3[0], u3[1], head_width=0.1, linewidth=5, length_includes_head=True, head_length=0.1, fc='k', ec='k')
plt.text(u1[0] + 0.1, u1[1] - 0.05, r"$v_1$", fontsize=22)
plt.text(u2[0] + 0.1, u2[1], r"$v'$", fontsize=22) # KPM
plt.text(u3[0] + 0.1, u3[1], r"$v_2$", fontsize=22)
plt.xlabel("$x_1$", fontsize=18)
plt.ylabel("$x_2$", fontsize=18, rotation=0)
plt.grid(True)

plt.subplot2grid((3,2), (0, 1))
plt.plot([-2, 2], [0, 0], "k-", linewidth=1)
plt.plot(X_proj1[:, 0], np.zeros(m), "bo", alpha=0.3)
plt.gca().get_yaxis().set_ticks([])
plt.gca().get_xaxis().set_ticklabels([])
plt.axis([-2, 2, -1, 1])
plt.grid(True)

plt.subplot2grid((3,2), (1, 1))
plt.plot([-2, 2], [0, 0], "k--", linewidth=1)
plt.plot(X_proj2[:, 0], np.zeros(m), "bo", alpha=0.3)
plt.gca().get_yaxis().set_ticks([])
plt.gca().get_xaxis().set_ticklabels([])
plt.axis([-2, 2, -1, 1])
plt.grid(True)

plt.subplot2grid((3,2), (2, 1))
plt.plot([-2, 2], [0, 0], "k:", linewidth=2)
plt.plot(X_proj3[:, 0], np.zeros(m), "bo", alpha=0.3)
plt.gca().get_yaxis().set_ticks([])
plt.axis([-2, 2, -1, 1])
plt.xlabel("$z_1$", fontsize=18)
plt.grid(True)

plt.tight_layout()
plt.savefig("../figures/pca_projected_variance.pdf", dpi=300)
plt.show()


# %%
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import norm
from matplotlib.animation import FuncAnimation
# matplotlib parameters to ensure correctness of Chinese characters
plt.rcParams["font.family"] = 'sans-serif'
plt.rcParams['font.sans-serif']=['Arial Unicode MS', 'SimHei'] # Chinese font
plt.rcParams['axes.unicode_minus']=False # correct minus sign

plt.rcParams["font.size"] = 16
plt.rcParams["xtick.labelsize"] = 16
plt.rcParams["ytick.labelsize"] = 16
plt.rcParams["axes.spines.top"] = False
plt.rcParams["axes.spines.right"] = False
#%%
class UpdateFigure:
    def __init__(self,
        ax:plt.Axes, x:np.ndarray, var_name:str, var_range:tuple, color, text_pos:tuple):
        """

        Args:
            ax (plt.Axes): _description_
            x (np.ndarray): _description_
            var_name (str): _description_
            var_range (tuple): _description_
            color (_type_): _description_
            text_pos (tuple): _description_
        """

        self.ax = ax
        self.x = x
        self.mean = var_range[0] if var_name=='mean' else 0.0
        self.std = var_range[0] if var_name=='std' else 1.0
        self.var_name = var_name
        self.var_range = var_range
        self.dx = (var_range[1]-var_range[0])/100.0
        self.c=color
        self.text_pos=text_pos

        y = norm.pdf(self.x, loc=self.mean, scale=self.std)
        self.line = self.ax.plot(self.x, y, color=self.c, zorder=0)

    def update_gauss(self, y):
        self.line[0].set_data(self.x,y)

    def __call__(self, i):
        # This way the plot can continuously run and we just keep
        # watching new realizations of the process
        if i < 101:
            if self.var_name == 'mean':
                y = norm.pdf(self.x,loc=self.mean+i*self.dx, scale=self.std)
            elif self.var_name == 'std':
                y = norm.pdf(self.x,loc=self.mean, scale=self.std+i*self.dx)
            self.update_gauss(y)
        elif i == 101:
            if self.var_name == 'mean':
                text = r'$\mu$ = %2d'%self.var_range[1]
            elif self.var_name == 'std':
                text = r'$\sigma$ = %2d'%self.var_range[1]
            self.ax.text(self.text_pos[0], self.text_pos[1],
                         text, ha='left',
                         fontsize=30, color=self.c,
                         transform=self.ax.transAxes)
        else:
            pass
        return self.line

#! ============================================================
#! evolve std
fig, ax = plt.subplots(1,1, dpi=400)
x = np.linspace(-6, 6, 401)
y = norm.pdf(x, loc=0, scale=1)
ax.plot(x, y, color='b', zorder=1)
ax.text(0.78, 0.88,
        r'$\sigma$ = %2d'%(1.0), ha='left',
        fontsize=30, color='b',
        transform=ax.transAxes)
ax.set_xlim(-6.0, 6.0)
ax.set_xticks([-6,-3,0,3,6])
ax.set_ylim(0, 0.5)
ax.spines['left'].set_position(('data', 0))

# create a figure updater
ud = UpdateFigure(ax, x, 'std', (1,2), 'g', (0.78,0.75))
anim = FuncAnimation(fig, ud, frames=121, blit=True)
anim.save('evolve_norm1.mp4', fps=60, dpi=400, codec='libx264', bitrate=-1, extra_args=['-pix_fmt', 'yuv420p'])

ud = UpdateFigure(ax, x, 'std', (2,3), 'r', (0.78,0.62))
anim = FuncAnimation(fig, ud, frames=121, blit=True)
anim.save('evolve_norm2.mp4', fps=60, dpi=400, codec='libx264', bitrate=-1, extra_args=['-pix_fmt', 'yuv420p'])

#! ============================================================
#! evolve mean
fig, ax = plt.subplots(1,1, dpi=400)
x = np.linspace(-6, 6, 401)
y = norm.pdf(x, loc=0, scale=1)
ax.plot(x, y, color='b', zorder=1)
ax.text(0.78, 0.88,
        r'$\mu$ = %2d'%(0.0), ha='left',
        fontsize=30, color='b',
        transform=ax.transAxes)
ax.set_xlim(-6.0, 6.0)
ax.set_xticks([-6,-3,0,3,6])
ax.set_ylim(0, 0.5)
ax.spines['left'].set_position(('data', 0))

# create a figure updater
ud = UpdateFigure(ax, x, 'mean', (0,2), 'g', (0.78,0.75))
anim = FuncAnimation(fig, ud, frames=121, blit=True)
anim.save('evolve_norm3.mp4', fps=60, dpi=400, codec='libx264', bitrate=-1, extra_args=['-pix_fmt', 'yuv420p'])

ud = UpdateFigure(ax, x, 'mean', (0,-2), 'r', (0.78,0.62))
anim = FuncAnimation(fig, ud, frames=121, blit=True)
anim.save('evolve_norm4.mp4', fps=60, dpi=400, codec='libx264', bitrate=-1, extra_args=['-pix_fmt', 'yuv420p'])
# %%


import math
import numpy as np
from linear_regression import *
from sklearn.datasets import make_regression
# Note: please don't add any new package, you should solve this problem using only the packages above.
#-------------------------------------------------------------------------
'''
    Problem 2: Apply your Linear Regression
    In this problem, use your linear regression method implemented in problem 1 to do the prediction.
    Play with parameters alpha and number of epoch to make sure your test loss is smaller than 1e-2.
    Report your parameter, your train_loss and test_loss
    Note: please don't use any existing package for linear regression problem, use your own version.
'''

#--------------------------

n_samples = 200
X,y = make_regression(n_samples= n_samples, n_features=4, random_state=1)
y = np.asmatrix(y).T
X = np.asmatrix(X)
Xtrain, Ytrain, Xtest, Ytest = X[::2], y[::2], X[1::2], y[1::2]

#########################################
## INSERT YOUR CODE HERE
w = train(Xtrain, Ytrain, alpha=0.1, n_epoch = 500)
yhat = Xtrain.dot(w)
yhat_test = Xtest.dot(w)
L = compute_L(yhat, Ytrain)
L_test = compute_L(yhat_test, Ytest)
assert np.allclose(L, 0., atol = 1e-2)
assert np.allclose(L_test, 0., atol = 1e-2)
print("Loss on training set:")
print(L)
print("Loss on training set is less than 1e-2:")
print(L<1e-2)
print( )
print("Loss on testing set:")
print(L_test)
print("Loss on testing set is less than 1e-2:")
print(L_test<1e-2)

loss_test = []
al = []
alpha = 0.015
while alpha < 0.1:
    al.append(alpha)
    w = train(Xtrain, Ytrain, alpha, n_epoch = 500)
    yhat = Xtrain.dot(w)
    yhat_test = Xtest.dot(w)
    L = compute_L(yhat, Ytrain)
    L_test = compute_L(yhat_test, Ytest)
    loss_test.append(L_test)
    alpha += 0.0001
print(loss_test)
import matplotlib.pyplot as plt
plt.xlabel("Alpha value")
plt.ylabel("Loss on test set")
plt.plot(al, loss_test, color="r")
plt.show()

# loss_test = []
# epoch = []
# for n_epoch in range(500, 1000):
#     epoch.append(n_epoch)
#     w = train(Xtrain, Ytrain, alpha=0.01, n_epoch=n_epoch)
#     yhat = Xtrain.dot(w)
#     yhat_test = Xtest.dot(w)
#     L = compute_L(yhat, Ytrain)
#     L_test = compute_L(yhat_test, Ytest)
#     loss_test.append(L_test)
# import matplotlib.pyplot as plt
# plt.xlabel("Epochs")
# plt.ylabel("Loss on test set")
# plt.plot(epoch, loss_test, color="b")
# plt.show()
#########################################


'''
Example of use a the optimization toolbox of SciPy.
The function optimized here are meaningless, and just given
as example. They ***are not*** related to the robotic models.
'''
import numpy as np
from scipy.optimize import fmin_bfgs, fmin_slsqp

def cost(x):
    '''Cost f(x,y) = x^2 + 2y^2 - 2xy - 2x '''
    x0 = x[0]
    x1 = x[1]
    return -1 * (2 * x0 * x1 + 2 * x0 - x0**2 - 2 * x1**2)

def constraint_eq(x):
    ''' Constraint x^3 = y '''
    return np.array([x[0]**3 - x[1]])

def constraint_ineq(x):
    '''Constraint x>=2, y>=2'''
    return np.array([x[0] - 2, x[1] - 2])

class CallbackLogger:
    def __init__(self):
        self.nfeval = 1

    def __call__(self, x):
        print('===CBK=== {0:4d}   {1: 3.6f}   {2: 3.6f}'.format(self.nfeval, x[0], x[1], cost(x)))
        self.nfeval += 1

x0 = np.array([0.0, 0.0])
# Optimize cost without any constraints in BFGS, with traces.
xopt_bfgs = fmin_bfgs(cost, x0, callback=CallbackLogger())
print('\n *** Xopt in BFGS = %s \n\n\n\n' % str(xopt_bfgs))

# Optimize cost without any constraints in CLSQ
xopt_lsq = fmin_slsqp(cost, [-1.0, 1.0], iprint=2, full_output=1)
print('\n *** Xopt in LSQ = %s \n\n\n\n' % str(xopt_lsq))

# Optimize cost with equality and inequality constraints in CLSQ
xopt_clsq = fmin_slsqp(cost, [-1.0, 1.0], f_eqcons=constraint_eq, f_ieqcons=constraint_ineq, iprint=2, full_output=1)
print('\n *** Xopt in c-lsq = %s \n\n\n\n' % str(xopt_clsq))


import sympy as sym
import numpy as np

V, t, I, w, dt = sym.symbols('V t I w dt')  # global symbols
f = None  # global variable for the source term in the ODE

def ode_source_term(u):
    """Return the terms in the ODE that the source term
    must balance, here u'' + w**2*u.
    u is symbolic Python function of t."""
    return sym.diff(u(t), t, t) + w**2*u(t)

def residual_discrete_eq(u):
    """Return the residual of the discrete eq. with u inserted."""
    R = DtDt(u, dt) + w**2*u(t) - f
    return sym.simplify(R)

def residual_discrete_eq_step1(u):
    """Return the residual of the discrete eq. at the first
    step with u inserted."""
    half = sym.Rational(1,2)
    R = u(t+dt) - I - dt*V - \
        half*dt**2*f.subs(t, 0) + half*dt**2*w**2*I
    R = R.subs(t, 0)  # t=0 in the rhs of the first step eq.
    return sym.simplify(R)

def DtDt(u, dt):
    """Return 2nd-order finite difference for u_tt.
    u is a symbolic Python function of t.
    """
    return (u(t+dt) - 2*u(t) + u(t-dt))/dt**2

def main(u):
    """
    Given some chosen solution u (as a function of t, implemented
    as a Python function), use the method of manufactured solutions
    to compute the source term f, and check if u also solves
    the discrete equations.
    """
    print '=== Testing exact solution: %s ===' % u(t)
    print "Initial conditions u(0)=%s, u'(0)=%s:" % \
          (u(t).subs(t, 0), sym.diff(u(t), t).subs(t, 0))

    # Method of manufactured solution requires fitting f
    global f  # source term in the ODE
    f = sym.simplify(ode_source_term(u))

    # Residual in discrete equations (should be 0)
    print 'residual step1:', residual_discrete_eq_step1(u)
    print 'residual:', residual_discrete_eq(u)

def linear():
    """Test linear function V*t+I: u(0)=I, u'(0)=V."""
    main(lambda t: V*t + I)

def quadratic():
    """Test quadratic function q*t**2 + V*t + I."""
    q = sym.Symbol('q')  # arbitrary constant in t**2 term
    u_e = lambda t: q*t**2 + V*t + I
    main(u_e)

def cubic():
    r, q = sym.symbols('r q')
    main(lambda t: r*t**3 + q*t**2 + V*t + I)

def solver(I, V, f, w, dt, T):
    """
    Solve u'' + w**2*u = f for t in (0,T], u(0)=I and u'(0)=V,
    by a central finite difference method with time step dt.
    f(t) is a callable Python function.
    """
    dt = float(dt)
    Nt = int(round(T/dt))
    u = np.zeros(Nt+1)
    t = np.linspace(0, Nt*dt, Nt+1)

    u[0] = I
    u[1] = u[0] - 0.5*dt**2*w**2*u[0] + 0.5*dt**2*f(t[0]) + dt*V
    for n in range(1, Nt):
        u[n+1] = 2*u[n] - u[n-1] - dt**2*w**2*u[n] + dt**2*f(t[n])
    return u, t

def test_quadratic_exact_solution():
    """Verify solver function via quadratic solution."""
    # Transform global symbolic variables to functions and numbers
    # for numerical computations
    global p, V, I, w
    p, V, I, w = 2.3, 0.9, 1.2, 1.5
    global f, t
    u_e = lambda t: p*t**2 + V*t + I # use p, V, I, w as numbers
    f = ode_source_term(u_e)         # fit source term
    f = sym.lambdify(t, f)           # make function numerical

    dt = 2./w
    u, t = solver(I=I, V=V, f=f, w=w, dt=dt, T=3)
    u_e = u_e(t)
    error = np.abs(u - u_e).max()
    tol = 1E-12
    assert error < tol
    print 'Error in computing a quadratic solution:', error

if __name__ == '__main__':
    linear()
    quadratic()
    cubic()
    test_quadratic_exact_solution()


#This program is used to represent the k-means cluster algorithm as presented in class
import numpy as np
import matplotlib.pyplot as plt

data = np.loadtxt("C:\\Users\David\Documents\CS445\GMM_data_fall2019.txt")
k= 7
len = data.__len__()
centroids = np.zeros((k,2))

#Get random points for the centroids
for i in range(0,k):
 rand_index = np.random.choice(data.__len__(),1)
 centroids[i] = data[rand_index]

#Assigns each point to a cluster
#Goes each datapoint and finds the centroid closest to it
#Places the point in the corresopnding cluster
def get_clusters(data, centroids):
    clusters = [[] for i in range(k)]
    for i in range(0,len):
        min_dist = 1000.0
        for j in range(0,k):
           p1 = centroids[j]
           p2 = data[i]
           dist = np.linalg.norm(p1 - p2)
           if dist < min_dist:
               index = j
               min_dist = dist
        point = data[i]
        clusters[index].append(point)
    return clusters

#Calculates the new_means for each cluster
#Finds the total x and y value for each cluster, then divides each by the length of the cluster
#Returns the list of new means/ centroids
def get_means(clusters):
    new_means = np.zeros((k, 2))

    for i in range(0,k):
        x_tot = 0
        y_tot = 0
        cluster_len = clusters[i].__len__()
        for j in range(0,cluster_len):
            point = clusters[i][j]
            x_tot += point[0]
            y_tot += point[1]

        if cluster_len == 0:
            cluster_len = 1

        new_means[i] = [x_tot/float(cluster_len), y_tot/float(cluster_len)]
    return new_means

#Checks if the difference between the old centroids and the new ones are different
#Returns False if they are
#Returns True if they aren't
#Has a tolerance of .2 in difference
def check_means(centroids, new_means):
    done = True
    for i in range(0,k):
        centroid_x = round(centroids[i][0],2)
        new_means_x = round(new_means[i][0],2)
        centroid_y = round(centroids[i][1],2)
        new_means_y = round(new_means[i][1],2)

        if np.abs(centroid_x-new_means_x) >= .2 or np.abs(centroid_y-new_means_y) >= .2:
           done = False

    return done

done = False
count = 0
#Execute the k-means algorithm until done or 100 times
while not done and count <= 100:
    clusters = get_clusters(data,centroids)
    new_means = get_means(clusters)
    done = check_means(centroids,new_means)
    count += 1
    if not done:
        centroids = new_means

#Handle Plotting
colors = ['r','b','g','y','k','c','m']
#assign each data point to the correct cluster by color for the plot
for i in range(0,k):
    for j in range(0,clusters[i].__len__()):

        plt.scatter(clusters[i][j][0],clusters[i][j][1],15,c=colors[i])

plt.show()


#!/usr/bin/env python
"""
Let's say we play a game where I keep flipping a coin until I get
heads. If the first time I get heads is on the nth coin, then I pay
you 2n-1 dollars. How much would you pay me to play this game?

You should end up with a sequence that you need to find the closed
form of. If you don't know how to do this, write some python code that
sums the first 100.

E(W) = sum_{n >= 1} (2n-1)/2^n = 3

"""

import matplotlib.pyplot as plt
import numpy as np

## simulate the number of flips before heads
def coin():
    tails, num_flips = True, 0
    while tails:
        num_flips += 1
        if np.random.binomial(1,0.5):
            tails = False
    return num_flips

if __name__ == '__main__':

    ## simulate
    flips = [coin() for k in xrange(10000)]

    ## get the distribution of counts condition on the number of flips
    range_flips = range(1, max(flips) + 1)
    counts = np.array([flips.count(k)*1. for k in range_flips])

    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.bar(range_flips,counts,alpha=0.4)
    ax.set_ylabel("counts")
    ax.set_xlabel("num flips to win")

    #print [int(i) for i in counts]

    winnings = sum([counts[k - 1]*(2*(k)-1)/sum(counts) for k in range_flips])

    #print range_flips
    print winnings

    plt.show()


import numpy as np
import matplotlib.pyplot as plt

def data_produce():

    # ----------------
    # 产 生 数 据
    # ----------------

    x1 = np.random.randint(0,1000,50)
    y1 = np.random.randint(0,1000,50)
    x2 = np.random.randint(1000,2000,50)
    y2 = np.random.randint(1000,2000,50)

    x = np.hstack((x1,x2))
    y = np.hstack((y1,y2))

    final_data = []

    for i in range(100):
        data = [x[i],y[i]]
        if(i < 50):
            data_dict = {'data':data,'flag':-1}
        else:
            data_dict = {'data':data, 'flag':1}
        final_data.append(data_dict)

    return final_data

def perceptron(x):

    w = np.ones(2)
    b = 0
    a = 3
    all_true = False

    while(not all_true):
        update_w = 0
        update_b = 0
        wrong_num = 0
        for data_dict in x:
        # ------------
        # 遍历所有的点
        # ------------
            x_data = np.array(data_dict['data'])
            judge = data_dict['flag']*(np.dot(x_data,w) + b)
            if judge < 0:
                wrong_num += 1
                print('wrong:', data_dict['data'])
                update_w += data_dict['flag']*np.array(data_dict['data'])
                update_b += data_dict['flag']

        print('wrong_num',wrong_num)
        if wrong_num == 0:
            all_true = True
            break
        w = w + a*update_w/wrong_num
        b = b + a*update_b/wrong_num
        print('w:',w)
        print('b',b)

    return w,b

if __name__ == "__main__":
    x = data_produce()
    w,b = perceptron(x)
    testx1 = -1000
    testy1 = testx1 * w[0] / (-1 * w[1]) + b/(-1 * w[1])
    testx2 = 3000
    testy2 = testx2 * w[0] / (-1 * w[1]) + b/(-1 * w[1])

    x1 = np.random.randint(0,1000,50)
    y1 = np.random.randint(0,1000,50)
    x2 = np.random.randint(1000,2000,50)
    y2 = np.random.randint(1000,2000,50)
    plt.scatter(x1,y1)
    plt.scatter(x2, y2)
    plt.plot([testx1,testx2],[testy1,testy2])
    plt.show()


#!/usr/bin/env python

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

def grad(y, x):
    dy = np.diff(y)
    dx = np.diff(x)
    dydx = dy / dx
    return np.hstack([dydx, 0])

def moving_average(a, n=3) :
    ret  = np.cumsum(a, dtype=float)
    ret[n:] = ret[n:] - ret[:-n]
    return ret[n - 1:] / n

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='compute velocity from trajectory')
    parser.add_argument('--avgbins', '-a', type=int, action='store', default=5, required=False,
                        help='number of bins over which to average velocity')
    parser.add_argument('trajectory_file')
    args = parser.parse_args()

    a = int(args.avgbins)

    traj = np.loadtxt(args.trajectory_file)

    x = traj[:,4]
    y = traj[:,8]

    t = traj[:, 0] - traj[0, 0]
    vx = grad(x, t)
    vy = grad(y, t)

    vxa   = np.hstack([np.zeros(a-1), moving_average(vx,a)])
    vya   = np.hstack([np.zeros(a-1), moving_average(vy,a)])
    vabs  = np.sqrt(np.square(vx) + np.square(vy))
    vabsa = np.sqrt(np.square(vxa) + np.square(vya))

    a = np.transpose(np.vstack([t, vabs, vabsa]))

    imax = np.argmax(vabsa)
    print "max avg velocity: %f m/s = %f km/h = %f mph at time: %f" % (vabsa[imax], vabsa[imax]*3.6, vabsa[imax]*2.23694, t[imax])

#    for row in a:
#        print "%f  %f %f" % (row[0], row[1], row[2])


import numpy as np

def relu(x):
    return np.maximum(x, 0)

def relu_derv(x):
    # y = relu(x) is not differentiable at x = 0.
    # if y > 0, derivative = 1
    # otherwise, derivative = 0
    return np.sign(x)

def sigmoid(x):
    return np.exp(-np.maximum(-x, 0)) / (1.0 + np.exp(-np.abs(x)))

def sigmoid_derv(x):
    # derivative of sigmoid.
    return x * (1 - x)

def tanh(x):
    return 2 * sigmoid(2*x) - 1

def tanh_derv(x):
    return (1.0 + x) * (1.0 - x)

def sigmoid_cross_entropy_with_logits(pt, x):
    # pt: p(true)
    # 1-pt : p(false)
    return np.maximum(x, 0) - x * pt + np.log(1 + np.exp(-np.abs(x)))

def sigmoid_cross_entropy_with_logits_derv(pt, x):
    # pt: p(true)
    # 1-pt : p(false)
    return -pt + sigmoid(x)

def softmax(x):
    # x: (batch, class)
    max_elem = np.max(x, axis=1)
    diff = (x.transpose() - max_elem).transpose()
    exp = np.exp(diff)
    sum_exp = np.sum(exp, axis=1)
    probs = (exp.transpose() / sum_exp).transpose()
    return probs

def softmax_cross_entropy_with_logits(labels, logits):
    # H(P,Q) = -SUM p_i log (q_i + eps)
    # eps: epsilon
    eps = 1.0e-10

    probs = softmax(logits)
    return -np.sum(labels * np.log(probs + eps), axis=1)

def softmax_cross_entropy_with_logits_derv(labels, logits):

    return softmax(logits) - labels

def onehot(x, dim_x):
    y = np.eye(dim_x)[np.array(x).astype(int)]
    return y


import numpy as np

def softmax(scores):
    """
    Computes only the softmax activation
    :param scores is a NxD matrix of N scores for D classes
    :return a NxD matrix with the probabilities for each class for each sample
    """
    log_c = -np.max(scores, axis=1)
    scores_better_numeric = np.exp((scores.T + log_c).T)
    sum_scores = np.sum(scores_better_numeric, axis=1)
    probabilities = (scores_better_numeric.T / sum_scores).T

    return probabilities

def softmax_loss(W, x, y, reg=0):
    """
    Computes the softmax loss function.
    """

    num_train = x.shape[0]
    scores = np.dot(x, W.T)
    probabilities = softmax(scores)

    loss = -np.sum(np.log(probabilities[np.arange(num_train), y])) / num_train
    loss += 0.5 * reg * np.sum(W * W)

    probabilities[np.arange(num_train), y] -= 1
    dW = np.dot(probabilities.T, x) / num_train
    dW += reg * W

    return loss, dW

def logistic(scores):
    probabilities = 1.0 / (1.0 + np.exp(-scores))
    return probabilities


import numpy as np

# Calculates the softmax of vector x with given temperature
def softmax(x, temp):
    x = x / temp # scale by temperature
    z = x - np.max(x) # substract max to prevent overflow of softmax
    return np.exp(z)/np.sum(np.exp(z)) # compute softmax


import numpy as np
from scipy import interpolate

class Drone:
    def __init__(self,waypointPositions,waypointSpeeds,numSteps):
        self.waypointPositions = waypointPositions #m
        self.waypointSpeeds = waypointSpeeds #m/s

        self.numSteps = numSteps #This is somewhat accurate. It's the resolution essentially

        #Calculating the time it should take to finish each segment of the set of waypoints
        self.waypointTimes = []
        for i in range(1,len(self.waypointPositions)):
            distance = np.linalg.norm(np.subtract(self.waypointPositions[i],self.waypointPositions[i-1]))
            waypointTime = distance / self.waypointSpeeds[i-1]
            self.waypointTimes.append(waypointTime)

        #Sum of all of the waypoint times is the total time of the mission
        self.totalTime = np.sum(self.waypointTimes)

    def interpolate(self):
        self.totalPos = []
        for i in range(1,len(self.waypointPositions)):

            #Determine how fast each XYZ component should go to follow m/s desired
            posDiff = np.subtract(self.waypointPositions[i],self.waypointPositions[i-1]) #Find difference of pos
            normPosDiff = np.linalg.norm(posDiff) #3D Length of pos diff
            speedMultVals = posDiff / normPosDiff #Pos diff in unit vector terms
            xyzSpeeds = self.waypointSpeeds[i-1] * speedMultVals #Speeds that each component needs to go

            X = [self.waypointPositions[i-1][0],self.waypointPositions[i][0]] #X values of waypoints
            Y = [self.waypointPositions[i-1][1],self.waypointPositions[i][1]] #Y values of waypoints
            Z = [self.waypointPositions[i-1][2],self.waypointPositions[i][2]] #Z values of waypoints

            #Scipy linear interpolation objects of X,Y & Z values
            fx = interpolate.interp1d([0,1],X)
            fy = interpolate.interp1d([0,1],Y)
            fz = interpolate.interp1d([0,1],Z)

            #Calculating number of steps based on total time and waypoint time
            numSteps = self.numSteps * (self.waypointTimes[i-1] / self.totalTime)

            #Linear interpolation
            newX = fx(np.linspace(0,1,num=int(numSteps)))
            newY = fy(np.linspace(0,1,num=int(numSteps)))
            newZ = fz(np.linspace(0,1,num=int(numSteps)))

            #Put in [X,Y,Z] format
            for ii in range(len(newX)):
                self.totalPos.append([newX[ii],newY[ii],newZ[ii]])
            print("Finished waypoint " + str(i-1) + "-" + str(i) + " at step number: " + str(len(self.totalPos)))
        #TODO Maybe add something if amount of scans needs to be exact
        return np.array(self.totalPos)

if __name__ == "__main__":
    waypoints = [[0,0,0],[0,0,5],[5,0,5],[0,0,5],[0,0,0]] #m
    speeds = [1,2,2,1] #m/s
    numSteps = 4200
    x = Drone(waypoints,speeds,numSteps)

    pos = x.interpolate()


# coding=utf-8
#矩阵常用操作
import numpy as np
nd14 = np.arange(9).reshape([3, 3])
#矩阵转置
np.transpose(nd14)
#矩阵乘法运算
a = np.arange(12).reshape([3, 4])
b = np.arange(8).reshape([4, 2])
a.dot(b)
#求矩阵的迹
a.trace()
#计算矩阵行列式
np.linalg.det(nd14)
#计算逆矩阵
c = np.random.random([3, 3])
np.linalg.solve(c, np.eye(3))

'''
diag:以一维数组方式返回方阵对角线元素
dot:矩阵乘法
trace:求迹，即对角线元素的和
det:计算行列式
eig:计算特征值和特征向量
inv:计算方阵的逆
qr:计算qr分解
svd:计算奇异值分解svd
solve:解线性方程组Ax = b,其中A为方阵
lstsq:计算Ax = b的最小二乘解
'''


#!/usr/bin/python3

import matplotlib.pyplot as plt
import numpy as np
import scipy.special

"""
Compute the area of a closed Bezier curve specified by
its control points.
"""
def bezier_area(P):
    R = np.array([[0, 1],
                  [-1, 0]])

    N = P.shape[0]-1
    A = 0
    for ii in range(1, N+1):
        for jj in range(0, ii):
            B = scipy.special.binom(
                N, ii) * scipy.special.binom(N, jj) / scipy.special.binom(2*N, ii+jj)
            D = jj/(ii+jj) - (N-jj)/(2*N-ii-jj)
            S = np.dot(P[ii, :], np.matmul(R, P[jj, :]))
            A += B * D * S

    return A

"""
Compute the approximate area of a Bezier curve by sampling
it in multiple points, and running a shoelace algorithm on
the resulting polygon.
"""
def approx_bezier_area(P, num_samples):
    def shoelace(x, y):
        return 0.5*np.abs(np.dot(x, np.roll(y, 1))-np.dot(y, np.roll(x, 1)))

    def bezier_interp(P, t):
        N = P.shape[0]-1
        val = np.zeros((t.shape[0], 2), dtype='float')
        for ii in range(0, N+1):
            b = scipy.special.binom(N, ii)
            c = b * np.power(t, ii) * np.power(1-t, N-ii)
            val += c[:, np.newaxis] * P[ii, :]
        return val

    N = P.shape[0]-1
    tt = np.linspace(0, 1, num_samples)
    pts = bezier_interp(P, tt)
    return shoelace(pts[:, 0], pts[:, 1])

def main():
    P = np.array([[-0.5, -0.5], [1, -1.8], [1.5, -5],
                 [0.6, -2.3], [1, 1], [-1, 1], [-0.5, -0.5]])

    Approx = approx_bezier_area(P, 100)
    print(f'the approximate area is {Approx}')

    Area = bezier_area(P)
    print(f'the exact area is {Area}')

if __name__ == '__main__':
    main()


import matplotlib.pyplot as plt
import numpy as np
# In this code we can give a prompt value for initial guess
# and also number of iterations
# def forward_diff(x,y):
#
# e=10**(-4)
# a=x
# b=y
#
#  def func(x):
#     return x**3-20
# funa=func(a)
# funb=func(b)
# # print(func(a))
# # print(func(b))
# if abs((b-a)/b)>e:
#     b= b-(funa*(b-a))/(funb-funa)
# return b
#print(forward_diff(0,1))
def newton_rapshon2(fun, p, q, n, e):
    a = p
    b = q
    #i=0
    #while i<n:
    for val in range(0, n):
        funca = fun(a)
        funcb = fun(b)
        if abs(funca) < e:  #                abs((b-a)/b)<e:
            print("Found solution after", val, "iterations")
            return a
        a = a - (funca * (b - a)) / (funcb - funca)
    else:
        print("exceeded maximum iterations")
    return None

fun = lambda x: x ** 3 - 20

result = newton_rapshon2(fun, 2, 3, 20, 10 ** (-4))
print("The value of the root is:", "%.5f" % result)

x = np.linspace(-5, 5, 50)
f = x ** 3 - 20

fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.spines['left'].set_position('center')
ax.spines['bottom'].set_position('zero')
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.xaxis.set_ticks_position('bottom')
ax.yaxis.set_ticks_position('left')
#plot the function
plt.plot(x, f, 'g', label='f(x)=x^3-20')

plt.xlabel('x')  # naming the x axis
plt.ylabel('f(x)')  # naming the y axis

# giving a title to my graph
plt.legend(loc='upper left')
#plt.title('f(x)=x^3-20')
plt.savefig("Newton_raphson2.png")
plt.show()


import numpy as np

def numerical_grad_no_batch(f, x):
    h = 1e-4
    grad = np.zeros_like(x)  # gradient will have the same shape as x

    for idx in range(x.size):
        tmp_val = x[idx]

        x[idx] = float(tmp_val) + h
        fxh1 = f(x)

        x[idx] = float(tmp_val) - h
        fxh2 = f(x)

        grad[idx] = (fxh1 - fxh2) / (2 * h)
        x[idx] = tmp_val
    return grad

def numerical_gradient(f, x):
    if x.ndim == 1:
        return numerical_grad_no_batch(f, x)
    grad = np.zeros_like(x)
    for idx, x_row in enumerate(x):
        grad[idx] = numerical_grad_no_batch(f, x_row)
    return grad

if __name__ == '__main__':
    def simple_func(x):
        if x.ndim == 1:
            return (x ** 2).sum()
        return (x ** 2).sum(axis=1)

    print(f"let's calculate gradient at [-4,4]")
    grad = numerical_grad_no_batch(simple_func, np.array([-4, 4], dtype=float))
    print(f"grad is {grad}")

    x = 4 * np.random.randn(11, 2)
    grad_batch = numerical_gradient(simple_func, x)
    for idx, grad_row in enumerate(grad_batch):
        print(f"gradient of {x[idx]} is {grad_row}")


#!/bin/python3

import numpy as np

def rodrigues(z,r,j):
    """
    Compute the directions about a cone using the rodrigues angle formula.

   `z` is the vector of the central axis of the cone.

   `r` is the radius of the cone that controls the size of the cone.

   `j` is the number of directions in the cone.

    """
    z /= np.linalg.norm(z)
    z0 = np.zeros(3)
    if np.any(z == 0):
        z0[z == 0] = 1
    else:
        z0[0] = 2/z[0]
        z0[1] = -1/z[1]
        z0[2] = -1/z[2]
    z0 /= np.linalg.norm(z0)
    z0 *= r
    z0 = z + z0
    z0 /= np.linalg.norm(z0)
    B = np.cross(z,z0)
    C = np.dot(z,z0)*z
    directions = np.zeros((j,3))
    for i in range(j):
        x = 2*np.pi*(i+1)/j
        directions[i,:] = z0*np.cos(x)+B*np.sin(x)+C*(1-np.cos(x))
    return directions

def generate_equidistributed_points(desired_number, N, hemisphere=False):
    """
    Generate Equidistributed points on a sphere / hemi-sphere.

    `desired_number` is the desired number of equidistributed points on the 2-sphere.

    `N` is the initial number of points that the algorithm will try to generate. If the number of points generated is less than the desired number, the function will increment `N`.

    If `hemisphere` is set to true, it generates points over hemisphere instead of over whole sphere.
    """
    if hemisphere:
        a = 2*np.pi/N
        d = np.sqrt(a)
        M_theta = int(round(np.pi*.5/d))
        d_theta = np.pi*.5/M_theta
    else:
        a = 4*np.pi/N
        d = np.sqrt(a)
        M_theta = int(round(np.pi/d))
        d_theta = np.pi/M_theta
    d_phi = a/d_theta
    points = []
    for i in range(M_theta):
        if hemisphere:
            theta = np.pi * .5 * i / M_theta
        else:
            theta = np.pi * (i + 0.5) / M_theta
        M_phi = int(round(2*np.pi*np.sin(theta)/d_phi))
        for j in range(M_phi):
            phi = 2*np.pi*j/M_phi
            point = [np.sin(theta)*np.cos(phi),np.sin(theta)*np.sin(phi),np.cos(theta)]
            point /= np.linalg.norm(point)
            points.append(point)
    points = np.array(points)
    if points.shape[0] < desired_number:
        return generate_equidistributed_points(desired_number,N+1,hemisphere)
    else:
        return points

def generate_equidistributed_cones(n_cone, cap_radius = 0.1, n_direction_per_cone = 1, hemisphere=False):
    """
    Generate equidistributed cones that are equidistributed about the sphere.

    It first generates equidistributed points, then use the rodrigues angle formula to compute cones about those points.

    `num_directions` is the number of equidistributed directions we want on the sphere.

    `cap_radius` is the radius of the cones we generate (determines the size of each cone).

    `directions_per_cone` is the number of directions we want generated within each cone.

    If `hemisphere` is set to True, it generates points over hemisphere instead of over whole sphere.
    """
    sphere = generate_equidistributed_points(n_cone, n_cone, hemisphere)
    directions = []
    for i in range(n_cone):
        directions.append(sphere[i]/np.linalg.norm(sphere[i]))
        if n_direction_per_cone > 1:
            for direction in rodrigues(sphere[i],cap_radius,n_direction_per_cone-1):
                direction /= np.linalg.norm(direction)
                directions.append(direction)
    return np.array(directions)


from typing import Sequence, Union

import numpy as np
from numba import njit

from numfun.function import Function

# noinspection PyPep8Naming
@njit
def polyfit_jit(x: np.array, y: np.array, n: int, a: float, b: float) -> tuple:
    """Jitted version of polyfit, see polyfit for details.

    :param x: nodes
    :param y: data
    :param n: degree of the polynomial fit
    :param a: left end point of domain
    :param b: right end point of domain
    :return: the output of np.linalg.lstsq()
    """
    m = len(x)
    Tx = np.zeros((m, n + 1))
    Tx[:, 0] = np.ones(m)
    x_map = 2.0 * (x - a) / (b - a) - 1.0
    Tx[:, 1] = x_map
    for k in range(1, n):
        Tx[:, k + 1] = 2.0 * x_map * Tx[:, k] - Tx[:, k-1]

    # TODO: this is not compiling :(
    # Initialize variables for jit:
    c = np.zeros((n+1,))  # noqa
    residuals = np.zeros((1,))  # noqa
    rank = int(0)  # noqa
    singular_values = np.zeros((n+1,))  # noqa

    c, residuals, rank, singular_values = np.linalg.lstsq(Tx, y, rcond=None)

    return c, residuals, rank, singular_values

def polyfit(
        x: np.ndarray,
        y: np.ndarray,
        degree: Union[int, Sequence[int]] = 1,
        domain: Union[None, np.ndarray, Sequence[float]] = None
) -> Function:
    """Least squares polynomial fitting to discrete data with piecewise domain splitting handled.

    :param x:
    :param y:
    :param degree: an array or a double len(degree) = len(domain) - 1
    :param domain: an array to specify where the breakpionts are
    :return:
    """

    if domain is None or len(domain) == 2:
        assert isinstance(degree, int)
        return polyfit_global(x, y, degree, domain)
    if len(domain) > 2:
        n_pieces = len(domain) - 1
        if isinstance(degree, Sequence):  # A list of degrees is passed
            assert n_pieces == len(degree), 'must specify degree for each domain'
            degrees = degree
        else:  # The degree passed is just an integer
            degrees = n_pieces * [int(degree)]
    else:
        raise AssertionError(f'domain = {domain}, domain must be for the form [a, b]')

    all_coefficients = n_pieces * [None]
    for j in range(n_pieces):
        a, b = domain[j], domain[j+1]
        idx = (a <= x) & (x <= b)
        if np.sum(idx) == 0:
            c = np.array([])
        else:
            xj, yj = x[idx], y[idx]
            f = polyfit_global(xj, yj, degree=degrees[j], domain=[a, b])
            c = f.coefficients[0].copy()
        all_coefficients[j] = c

    return Function(coefficients=all_coefficients, domain=domain)

def polyfit_global(
        x: np.ndarray,
        y: np.ndarray,
        degree: int = 1,
        domain: Union[None, Sequence[float], np.ndarray] = None
) -> Function:
    """Degree n least squares polynomial approximation of data y taken on points x in a domain.

    :param x: x-values, np array
    :param y: y-values, i.e., data values, np array
    :param degree: degree of approximation, an integer
    :param domain: domain of approximation
    :return:
    """

    if domain is None:
        domain = [np.min(x), np.max(x)]

    domain = 1.0 * np.array(domain)
    a = domain[0]
    b = domain[-1]
    assert len(x) == len(y), f"len(x) = {len(x)}, while len(y) = {len(y)}, these must be equal"
    assert degree == int(degree), f'degree = {degree}, degree must be an integer'

    n = int(degree)

    # map points to [-1, 1]
    m = len(x)
    x_normalized = 2.0 * (x - a) / (b - a) - 1.0
    # construct the Chebyshev-Vandermonde matrix:
    Tx = np.zeros((m, n+1))
    Tx[:, 0] = np.ones(m)
    if n > 0:
        Tx[:, 1] = x_normalized
        for k in range(1, n):
            Tx[:, k + 1] = 2.0 * x_normalized * Tx[:, k] - Tx[:, k-1]

    # c, residuals, rank, singular_values = polyfit_jit(x, y, n, a, b)
    c, residuals, rank, singular_values = np.linalg.lstsq(Tx, y, rcond=None)

    # Make a function:
    return Function(coefficients=c, domain=domain)

def main() -> None:
    import matplotlib.pyplot as plt
    x = np.linspace(0, 10, 11)
    y = x ** 2
    n = 2
    domain = [0, 10]
    f = polyfit(x, y, n, domain)
    plt.plot(x, y, '.')
    f.plot()

    x = np.linspace(0, 5, 201)
    y = x * (x < 2.0) + x ** 2 * ((x >= 2.0) & (x < 3.0)) + \
        x ** 3 * ((x >= 3.0) & (x < 4.0)) + x ** 4 * (x >= 4.0)
    domain = [0, 1, 2, 3, 4, 5]
    degrees = [0, 1, 2, 3, 4]
    f = polyfit(x, y, degree=degrees, domain=domain)
    f.plot()

if __name__ == '__main__':
    main()


import numpy as np

def solve_bandit(bandit, eps=0, steps=1000, ucb=False, c=1):
    """
    Runs a greedy action selection method to get the best
    sequence of actions.
    Args:
        - bandit (KBandit): the k-armed bandit.
        - eps (float): probability of taking a random action.
        - steps (int): number of steps to run the method
        - ucb (boolean): whether or not to use the Upper Confidence Bound
            instead of greedy or epsilon-greedy approaches.
        - c (float): confidence level used when ucb is True.
    Returns:
        - numpy array of size (steps x 2). The first column
        contains the action taken, the second the reward.
    """
    # Initialize estimates and counts
    action_values = np.zeros(bandit.k)
    action_counts = np.zeros(bandit.k)
    results = np.zeros((steps, 2))

    for step in range(steps):
        # Select action according to selected method
        if ucb:
            # Use the Upper Confidence Bound criterion

            # An action not chosen so far is the maximizer by default
            zero_idx = np.where(action_counts == 0)[0]
            if len(zero_idx) > 0:
                action = zero_idx[0]
            else:
                action = np.argmax(action_values + c * np.sqrt(np.log(step + 1)/action_counts))
        else:
            # Use an epsilon-greedy approach
            if np.random.random() < eps:
                action = np.random.randint(bandit.k)
            else:
                action = np.argmax(action_values)

        # Get reward from bandit
        reward = bandit.get_reward(action)
        results[step, :] = [action, reward]

        # Update counts and estimate for the selected action
        action_counts[action] += 1
        action_values[action] += (reward - action_values[action])/action_counts[action]

    return results


'''
Functions for wrapping real numbers into cyclic intervals, especially
angles.

MIT License

Copyright (c) 2018 Standard Cognition

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
'''

# Scientific
import numpy as np

def wrap(x: float, l: float = 1.0) -> float:
    '''
    Map/wrap x into the interval [0.0, l) with 0.0 and l identified.

    Args:
        x: number to map.
        l: length of mod interval.

    Returns:
        The image of x in [0.0, l).
    '''
    return float(np.mod(x, l))

def wrap_0_to_2pi(x: float) -> float:
    '''
    Map/wrap an angle x into the interval [0.0, 2.0*np.pi) with 0.0 and
    2.0*np.pi identified.

    Args:
        x: angle in radians.

    Returns:
        Angle radians in [0.0, 2.0*np.pi).
    '''
    return wrap(x, 2.0*np.pi)

def wrap_mpi_to_pi(x: float) -> float:
    '''
    Map/wrap an angle x into the interval [-np.pi, np.pi) with -np.pi and
    np.pi identified.

    Args:
        x: angle in radians.

    Returns:
        Angle radians in [0.0, 2.0*np.pi).
    '''
    y = wrap(x, 2.0*np.pi)
    if y <= np.pi:
        return y
    return float(y - 2.0*np.pi)  # y > np.pi

def geodesic_difference(a: float, b: float) -> float:
    '''
    Geodesic difference on the circle between angles in radians.

    Args:
        a: angle in radians.
        b: angle in radians.

    Returns:
        Geodesic difference in radians.
    '''
    a_wrapped = wrap_0_to_2pi(a)
    b_wrapped = wrap_0_to_2pi(b)

    d = a_wrapped - b_wrapped
    d_magnitude = abs(d)
    d_alternate_magnitude = abs(2.0*np.pi - d_magnitude)

    if d_alternate_magnitude < d_magnitude:
        return float(-np.sign(d)*d_alternate_magnitude)
    return d

def geodesic_distance(a: float, b: float) -> float:
    '''
    Geodesic distance on the circle between angles in radians.

    Args:
        a: angle in radians.
        b: angle in radians.

    Returns:
        Geodesic distance in radians.
    '''
    a_wrapped = wrap_0_to_2pi(a)
    b_wrapped = wrap_0_to_2pi(b)

    d = a_wrapped - b_wrapped
    d_magnitude = abs(d)
    d_alternate_magnitude = abs(2.0*np.pi - d_magnitude)

    return min(d_magnitude, d_alternate_magnitude)


#
#  file:  birthday.py
#
#  Simulate the birthday paradox
#
#  RTK, 04-Jun-2020
#  Last update:  04-Jun-2020
#
################################################################

import numpy as np

# Simulate picking two people at random, probability of sharing a birthday
N = 100000
match = 0
for i in range(N):
    a = np.random.randint(0,364)
    b = np.random.randint(0,364)
    if (a == b):
        match += 1
print()
print("Probability of a random match = %0.6f" % (match/N,))
print()

# Simulate people in a room, N tests per M
M = 30
N = 100000
for m in range(2,M+1):
    matches = 0
    for n in range(N):
        match = 0
        b = np.random.randint(0,364,m)
        for i in range(m):
            for j in range(m):
                if (i != j) and (b[i] == b[j]):
                    match += 1
        if (match != 0):
            matches += 1
    print("%2d people: probability of at least one match %0.6f" % (m, matches/N))


import numpy as np
import scipy.fftpack as spfft
import cvxpy as cvx

def min_spacing(mylist):
    """
    Find the minimum spacing in the list.

    Args:
        mylist (list): A list of integer/float.

    Returns:
        int/float: Minimum spacing within the list.
    """
    # Set the maximum of the minimum spacing.
    min_space = max(mylist) - min(mylist)

    # Iteratively find a smaller spacing.
    for item in mylist:
        spaces = [abs(item - item2) for item2 in mylist if item != item2]
        min_space = min(min_space, min(spaces))

    # Return the answer.
    return min_space

def reconstruct_from_signal(angles, signals, error=0, verb=False):
    """
    Reconstruct the signal from the given angles and signals.

    Args:
        angles (list): List of angles.
        signals (list): List of signals.
        error: An error strength in the 2-norm distance.

    Returns:
        list: Reconstructed signal.
    """
    # Find the minimum spacing.
    spacing = min_spacing(angles)
    itt = int(2 * np.pi / spacing)
    # Make the discret Fourier transform matrix.
    idct_matrix = spfft.idct(np.identity(itt), norm='ortho', axis=0)
    # Make the angles integer-valued.
    angles_discrete = [int(angle / spacing) for angle in angles]
    m_vecs = idct_matrix[angles_discrete]
    vx = cvx.Variable(itt)
    objective = cvx.Minimize(cvx.norm(vx, 1))
    constraints = [cvx.norm(m_vecs * vx - signals, 2) <= error]
    prob = cvx.Problem(objective, constraints)
    result = prob.solve(verbose=verb)
    return idct_matrix @ np.squeeze(np.array(vx.value))

def sparse_reconstruct(angles, signals, magnify = 10, error=0, verb=False):
    """
    Reconstruct the signal from the given angles and signals.

    Args:
        angles (list): List of angles.
        signals (list): List of signals.
        error: An error strength in the 2-norm distance.

    Returns:
        list: Reconstructed signal.
    """
    # Find the minimum spacing.
    spacing = min_spacing(angles)
    itt = int(2 * np.pi / spacing)
#    print("length={}".format(itt))
    # Make the discret Fourier transform matrix.
    idct_matrix = spfft.idct(np.identity(itt), norm='ortho', axis=0)
    # Make the angles integer-valued.
    angles_discrete = [int(angle / spacing) for angle in angles]
    m_vecs = idct_matrix[angles_discrete]
    vx = cvx.Variable(itt)
    objective = cvx.Minimize(cvx.norm(vx, 1))
    constraints = [cvx.norm(m_vecs * vx - signals, 2) <= error]
    prob = cvx.Problem(objective, constraints)
    result = prob.solve(verbose=verb)
    fcoefficients = np.squeeze(np.array(vx.value))
    dim_enlarged = itt * magnify
    fcoefficients_enlarged = np.zeros(dim_enlarged)
    for i in range(itt):
        fcoefficients_enlarged[i*magnify] = fcoefficients[i]

    idct_matrix_enlarged = spfft.idct(np.identity(dim_enlarged), norm='ortho', axis=0)

    return idct_matrix_enlarged @ fcoefficients_enlarged


import numpy as np

def MonteCarlo_double(f, g, x0, x1, y0, y1, n):
    """
    Monte Carlo integration of f over a domain g>=0, embedded
    in a rectangle [x0,x1]x[y0,y1]. n^2 is the number of
    random points.
    """
    # Draw n**2 random points in the rectangle
    x = np.random.uniform(x0, x1, n)
    y = np.random.uniform(y0, y1, n)
    # Compute sum of f values inside the integration domain
    f_mean = 0
    num_inside = 0   # number of x,y points inside domain (g>=0)
    for i in range(len(x)):
        for j in range(len(y)):
            if g(x[i], y[j]) >= 0:
                num_inside = num_inside + 1
                f_mean = f_mean + f(x[i], y[j])
    f_mean = f_mean/num_inside
    area = num_inside/(n**2)*(x1 - x0)*(y1 - y0)
    return area*f_mean

def test_MonteCarlo_double_rectangle_area():
    """Check the area of a rectangle."""
    def g(x, y):
        return (1 if (0 <= x <= 2 and 3 <= y <= 4.5) else -1)

    x0 = 0;  x1 = 3;  y0 = 2;  y1 = 5  # embedded rectangle
    n = 1000
    np.random.seed(8)      # must fix the seed!
    I_expected = 3.121092  # computed with this seed
    I_computed = MonteCarlo_double(
        lambda x, y: 1, g, x0, x1, y0, y1, n)
    assert abs(I_expected - I_computed) < 1E-14

def test_MonteCarlo_double_circle_r():
    """Check the integral of r over a circle with radius 2."""
    def g(x, y):
        xc, yc = 0, 0  # center
        R = 2          # radius
        return  R**2 - ((x-xc)**2 + (y-yc)**2)

    # Exact: integral of r*r*dr over circle with radius R becomes
    # 2*pi*1/3*R**3
    import sympy
    r = sympy.symbols('r')
    I_exact = sympy.integrate(2*sympy.pi*r*r, (r, 0, 2))
    print('Exact integral: {:g}'.format(I_exact.evalf()))
    x0 = -2;  x1 = 2;  y0 = -2;  y1 = 2
    n = 1000
    np.random.seed(6)
    I_expected = 16.7970837117376384  # Computed with this seed
    I_computed = MonteCarlo_double(
        lambda x, y: np.sqrt(x**2 + y**2),
        g, x0, x1, y0, y1, n)
    print('MC approximation, {:d} samples: {:.16f}'\
          .format(n**2, I_computed))
    assert abs(I_expected - I_computed) < 1E-15

if __name__ == '__main__':
    test_MonteCarlo_double_rectangle_area()
    test_MonteCarlo_double_circle_r()


import numpy as np

def softmax(x, n_stable=True):
    ''' Compute softmax nonlinearity

    Args:
        x (ndarray): ndarray of inputs over which to take softmax.
        n_stable (bool): Whether to use numerically stable softmax defaults to True.

    Returns:
        ndarray: The softmax over the input.
    '''

    assert(isinstance(x, np.ndarray))
    # numerically stable, but slightly slower
    if n_stable:
        x = x - np.max(x, axis=1)[:, np.newaxis]

    out = np.exp(x)
    y = out / np.sum(out, axis=1)[:, np.newaxis]
    return y

def sigmoid(x):
    ''' Compute logistic sigmoid nonlinearity

    Args:
        x (ndarray): ndarray of inputs over which to take logistic sigmoid.

    Returns:
        ndarray: The logistic sigmoid of the input.
    '''

    assert(isinstance(x, np.ndarray))
    return 1 / (1 + np.exp(-x))

def tanh(x):
    ''' Compute hyperbolic tangent nonlinearity

    Multiplicative constants ensure that if input is zero mean and unit
    variance, the outout will also be zero mean and unit variance.
    Shown by LeCunn http://yann.lecun.com/exdb/publis/pdf/lecun-98b.pdf
    to help back propagation when inputs are z-scored but batch normalization
    is not performed at each layer.

    Args:
        x (ndarray): ndarray of inputs to over which to take hyperbolic tangent.

    Returns:
        ndarray: The hyperbolic tangent of the input.
    '''

    assert(isinstance(x, np.ndarray))
    # constants results in zero mean unit variance in zero mean unit variance out
    return 1.7159 * np.tanh(2*x/3)

def relu(x):
    ''' Compute rectified linear unit nonlinearity

    Args:
        x (ndarray): ndarray of inputs to over which to take ReLU.

    Returns:
        ndarray: The ReLU of the input.
    '''

    assert(isinstance(x, np.ndarray))
    return np.maximum(x, 0)

def swish(x):
    ''' Compute swish nonlinearity

    Activation function reported to perform better than ReLU in deep networks
    by Ramachandran et al. https://arxiv.org/abs/1710.05941

    Args:
        x (ndarray): ndarray of inputs to over which to take swish.

    Returns:
        ndarray: The swish of the input.
    '''

    assert(isinstance(x, np.ndarray))
    return x * sigmoid(x)

ACTIVATIONS = {'softmax': softmax,
               'sigmoid': sigmoid,
               'tanh': tanh,
               'relu': relu,
               'swish': swish}

def softmax_prime(x, y=None):
    ''' Compute derivative of softmax nonlinearity

    Args:
        x (ndarray): ndarray of inputs over which to take softmax derivative.
        y (ndarray): Cached ndarray of softmax(x) used to speed up calculation
            if available defaults to None indicating softmax must be recomputed

    Returns:
        ndarray: The derivative of softmax over the input.
    '''

    assert(isinstance(x, np.ndarray))
    if y is None:
        y = softmax(x)
    return y * (1 - y)

def sigmoid_prime(x, y=None):
    ''' Compute derivative of logistic sigmoid nonlinearity

    Args:
        x (ndarray): ndarray of inputs over which to take sigmoid derivative.
        y (ndarray): Cached ndarray of sigmoid(x) used to speed up calculation
            if available defaults to None indicating sigmoid must be recomputed

    Returns:
        ndarray: The derivative of sigmoid over the input.
    '''

    assert(isinstance(x, np.ndarray))
    if y is None:
        y = sigmoid(x)
    return y * (1 - y)

def tanh_prime(x, y=None):
    ''' Compute derivative of hyperbolic tangent nonlinearity

    Args:
        x (ndarray): ndarray of inputs over which to take tanh derivative.
        y (ndarray): Cached ndarray of tanh(x) used to speed up calculation
            if available defaults to None indicating tanh must be recomputed

    Returns:
        ndarray: The derivative of tanh over the input.
    '''

    assert(isinstance(x, np.ndarray))
    if y is None:
        y = tanh(x)
    # divide by 1.7159^2 to get pure tanh without multiplicative constant
    return 1.1439 * (1 - y * y / 2.9443)

def relu_prime(x, y=None):
    ''' Compute derivative of rectified linear unit nonlinearity

    Args:
        x (ndarray): ndarray of inputs over which to take ReLU derivative.
        y (ndarray): Not used exists to maintain common interface among all
            activation functions defaults to None

    Returns:
        ndarray: The derivative of ReLU over the input.
    '''

    assert(isinstance(x, np.ndarray))
    return (x > 0).astype(float)

def swish_prime(x, y=None):
    ''' Compute derivative of swish nonlinearity

    Args:
        x (ndarray): ndarray of inputs over which to take swish derivative.
        y (ndarray): Cached ndarray of swish(x) used to speed up calculation
            if available defaults to None indicating swish must be recomputed

    Returns:
        ndarray: The derivative of swish over the input.
    '''
    if y is None:
        y = sigmoid(x)
    else:
        # swish activation is x * sigmoid(x) so divide by x to get sigmoid
        y = y/x

    return y + x * sigmoid_prime(x, y=y)

DERIVATIVES = {'softmax': softmax_prime,
               'sigmoid': sigmoid_prime,
               'tanh': tanh_prime,
               'relu': relu_prime,
               'swish': swish_prime}

def cross_entropy(y, t):
    ''' Compute cross entropy loss

    Args:
        y (ndarray): ndarray the predicted distribution.
        t (ndarray): ndarray the target distribution.

    Returns:
        ndarray: The cross entropy loss between y and t.
    '''

    return -np.sum(t * np.log(y))/y.shape[0]

def mean_squared_error(y, t):
    ''' Compute mean squared error

    Args:
        y (ndarray): ndarray the predicted values.
        t (ndarray): ndarray the target values.

    Returns:
        ndarray: The mean squared error between y and t.
    '''

    return np.sum(np.square(t - y))/y.shape[0]

def mean_absolute_error(y, t):
    ''' Compute mean absolute error

    Args:
        y (ndarray): ndarray the predicted values.
        t (ndarray): ndarray the target values.

    Returns:
        ndarray: The mean absolute error between y and t.
    '''

    return np.sum(np.absolute(t - y))/y.shape[0]

LOSSES = {'cross_entropy': cross_entropy,
          'mean_squared_error': mean_squared_error,
          'mean_absolute_error': mean_absolute_error}


#Program wich solves the one-particle (time independent) Schrodinger
#equation for a potential specified in function potential(). This
#example is for the hydrogen atom. This is a translation of the C++
#code for chapter 12 in "Computational Physics", M. H. Jensen
#Translated to Python by Magnar K. Bugge

import numpy
import math
import sys
import computationalLib

#Read output file name from command line argument, abort if none is given
if len(sys.argv) == 2:
    outfilename = sys.argv[1]
else:
    print '\nError: name of output file must be given as command line argument.\n'
    sys.exit(0)

#Function for initialisation of parameters
def initialize():
    r_min = eval(raw_input('Min value of r: '))
    r_max = eval(raw_input('Max value of r: '))
    orb_l = eval(raw_input('Orbital angular momentum (l): '))
    max_step = eval(raw_input('Number of steps: '))

    return r_min,r_max,orb_l,max_step

#Function for outputting results to file
def output():
    outfile = open(outfilename,'w')
    outfile.write('Results:\nr_min = %f\nr_max = %f\nOrbital angular momentum (l) = \
%d\nNumber of steps = %d\nFive lowest eigenvalues:\n' %(r_min,r_max,orb_l,max_step))
    for i in xrange(5):
        outfile.write('%f\n' %(d[i]))

#Potential function (returns value of potential for given r)
def potential(r):

    return -2.0/r

#Here starts the main program

#Read in data from user
r_min,r_max,orb_l,max_step = initialize()

#Initialize constants
step = (r_max - r_min) / max_step
const_2 = -1.0 / step**2
const_1 = -2.0 * const_2
orb_factor = orb_l * (orb_l + 1)

#Calculate array of potential values
V = numpy.zeros(max_step+1,numpy.double)
for i in xrange(max_step+1):
    r = r_min + i*step
    V[i] = potential(r) + orb_factor/r**2 #(include centrifugal term)

#Calculate elements of the matrix to be diagonalized
d = numpy.zeros(max_step,numpy.double) #diagonal elements
e = numpy.zeros(max_step,numpy.double) #off-diagonal elements
z = numpy.zeros((max_step,max_step),numpy.double) #matrix for eigenvectors (only used as a dummy-argument to
                                                  #tqli() in the current version of this program)
for i in xrange(max_step):
    d[i] = const_1 + V[i+1]
    e[i] = const_2

    z[i,i] = 1 #(identity matrix)

#Diagonalize and obtain eigenvalues. The eigenvalues are stored in d.
computationalLib.pylib(cpp=False).tqli(d,e,z)

#Sort the eigenvalues (smallest to largest)
d = numpy.msort(d)

#Output to file
output()


import matplotlib.pyplot as plt
import numpy as np
from scipy.integrate import odeint
from sympy import pprint, Symbol, Function, Derivative, dsolve, solve, diff
import sympy as sp
from sympy.interactive import printing
printing.init_printing(use_latex = True)

f = Function('f');
x = Symbol('x');

# ODE model 1
def model1(y, x):
    dydx = 1 + x -y;
    return dydx;

model = f(x).diff(x) + 1 + x - f(x);
y_general = dsolve(model, f(x));
print('The general solution: ')
pprint(y_general);

y_special = dsolve(model,f(x), ics={f(0):0});
print('The special solution: ')
pprint(y_special);

# solution = solve(y_special.subs([(f(x), 1)]), x)
# print(solution)

# model 1
plt.figure(1)
# Direction field parameters
X_start = -15;
X_end = 15;
N_X_points = 30; # number of points in X direction
Y_start = -15;
Y_end = 15;
N_Y_points = N_X_points; # number of points in Y direction

X, Y = np.meshgrid(np.linspace(X_start, X_end, N_X_points), np.linspace(Y_start, Y_end, N_Y_points));
delta_X = np.ones((N_X_points, N_Y_points)); # direction vector x component
delta_Y = model1(Y, X); # direction vector y component
vector_normalization = np.sqrt(np.power(delta_X, 2) + np.power(delta_Y, 2));
delta_X = delta_X / vector_normalization; # normalized direction vector x component
delta_Y = delta_Y / vector_normalization; # normalized direction vector y component

# Plot direction field
plt.quiver(X, Y, delta_X, delta_Y, angles="xy");#, scale_units='xy', scale = 1);

# Plot integral curves
x_start = -8;
x_end = 12;
y_start = -15;
y_end = 15;
N_int_curves = 15; # number of solutions to plot
x = np.linspace(x_start, x_end, N_X_points * 100); # evaluate solution y(x) at x
y0_vector = np.linspace(y_start, y_end, N_int_curves); # vector of initial solutions
for solution_no in range(N_int_curves):
    y0 = y0_vector[solution_no]; # initial condition
    y = odeint(model1, y0, x, args=());
    plt.plot(x, y)

plt.xlim([X_start, X_end])
plt.ylim([Y_start, Y_end])
plt.xlabel('X axis')
plt.ylabel('Y axis')
plt.grid()
plt.show()

import numpy,from scipy,import sympy,from sympy