__author__ 		= "Lekan Molu"
__copyright__ 	= "2021, Hamilton-Jacobi Analysis in Python"
__license__ 	= "Molux Licence"
__maintainer__ 	= "Lekan Molu"
__email__ 		= "patlekno@icloud.com"
__status__ 		= "Completed"

import matplotlib.pyplot as plt
from skimage import measure
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import os, sys
from os.path import abspath, dirname, exists, join
sys.path.append(dirname(dirname(abspath(__file__))))

from Grids import createGrid
from InitialConditions import *
from Visualization.mesh_implicit import implicit_mesh

fig = plt.figure(figsize=(16, 9))
def get_grid():

	g3min = -.6*np.ones((3, 1),dtype=np.float64)
	g3max = +6*np.ones((3, 1),dtype=np.float64)
	g3N = 51*np.ones((3, 1),dtype=np.int64)
	g3 = createGrid(g3min, g3max, g3N, process=True)

	return g3

def slender_cylinder(g3):
	axis_align, radius=2, .5
	center = 2*np.ones((3, 1), np.float64)
	cylinder = shapeCylinder(g3, axis_align, center, radius);

	spacing = tuple(g3.dx.flatten().tolist())
	mesh = implicit_mesh(cylinder, level=0., spacing=spacing)

	ax = plt.gca()
	plt.clf()
	ax = fig.add_subplot(121, projection='3d')
	ax.add_collection3d(mesh)

	ax.set_xlabel("x-axis")
	ax.set_ylabel("y-axis")
	ax.set_zlabel("z-axis")

	ax.set_xlim(1.5, 3)
	ax.set_ylim(2.5, 4.0)
	ax.set_zlim(-2, 4.0)

	plt.tight_layout()
	plt.pause(5)

def cylinder_sphere(g3, savedict):
    spacing = tuple(g3.dx.flatten().tolist())

    # generate signed distance function for cylinder
    center = 2*np.ones((3, 1), np.float64)
    ignoreDim, radius=2, 1.5
    cylinder = shapeCylinder(g3, ignoreDim, center, radius);
    cyl_mesh = implicit_mesh(cylinder, level=0., spacing=spacing)

    fig = plt.figure(figsize=(16, 9))
    ax = fig.add_subplot(121, projection='3d')
    #ax.plot3D(g3.xs[0].flatten(), g3.xs[1].flatten(), g3.xs[2].flatten(), color='cyan')
    ax.add_collection3d(cyl_mesh)

    fontdict = {'fontsize':12, 'fontweight':'bold'}
    ax.set_xlabel("X-axis", fontdict = fontdict)
    ax.set_ylabel("Y-axis", fontdict = fontdict)
    ax.set_zlabel("Z-axis", fontdict = fontdict)
    ax.set_title('Zero Level Set: Cylinder', fontdict = fontdict)

    xlim = (min(cylinder[0].ravel()), max(cylinder[0].ravel()))
    ylim = (min(cylinder[1].ravel()), max(cylinder[1].ravel()))
    zlim = (min(cylinder[2].ravel()), max(cylinder[2].ravel()))

    gxlims = (min(g3.vs[0]), max(g3.vs[0]))
    gylims = (min(g3.vs[1]), max(g3.vs[1]))
    gzlims = (min(g3.vs[2]), max(g3.vs[2]))

    ax.set_xlim(xlim[0]-gxlims[0], xlim[1]-gxlims[1])
    ax.set_ylim(ylim[0]-gylims[0], ylim[1]-gylims[1])
    ax.set_zlim(0, zlim[1])

    sphere = shapeSphere(g3, center, radius=3)
    sphere_mesh = implicit_mesh(sphere, level=0., spacing=spacing, edge_color='k', face_color='g')

    ax2 = fig.add_subplot(122, projection='3d')
    #ax2.plot3D(g3.xs[0].flatten(), g3.xs[1].flatten(), g3.xs[2].flatten(), color='cyan')
    ax2.add_collection3d(sphere_mesh)
    ax2.view_init(elev=30., azim=10.)

    xlim = (min(sphere[0].ravel()), max(sphere[0].ravel()))
    ylim = (min(sphere[1].ravel()), max(sphere[1].ravel()))
    zlim = (min(sphere[2].ravel()), max(sphere[2].ravel()))

    gxlims = (min(g3.vs[0]), max(g3.vs[0]))
    gylims = (min(g3.vs[1]), max(g3.vs[1]))
    gzlims = (min(g3.vs[2]), max(g3.vs[2]))

    ax2.set_xlim(xlim[0]-gxlims[0], xlim[1]-gxlims[1])
    ax2.set_ylim(ylim[0]-gylims[0], ylim[1]-gylims[1])
    ax2.set_zlim(0, zlim[1])

    ax2.set_xlabel("X-axis", fontdict = fontdict)
    ax2.set_ylabel("Y-axis", fontdict = fontdict)
    ax2.set_zlabel("Z-axis", fontdict = fontdict)
    ax2.set_title('Zero Level Set: Sphere', fontdict = fontdict)

    plt.tight_layout()
    plt.show()

    if savedict["save"]:
        fig.savefig(join(savedict["savepath"],savedict["savename"]),
                    bbox_inches='tight',facecolor='None')

def main(savedict):
	"""
		Tests the visuals of an implicit function.

		Here, a cylinder generated  by a signed distance function from
		the nodes of a grid. The cylinder is specified by its radius and its
		distance from the center of the grid. This can be used to represent obstacles
		in a state space from which an agent must avoid.
	"""
	if savedict["save"] and not exists(savedict["savepath"]):
		os.makedirs(savedict["savepath"])
	plt.ion()

	g3 = get_grid()
	savedict["savename"] = "slender_cylinder.jpeg"
	slender_cylinder(g3)
	fig.canvas.draw()
	fig.canvas.flush_events()

	savedict["savename"] = "sphere_cyl.jpeg"
	cylinder_sphere(g3, savedict)
	fig.canvas.draw()
	fig.canvas.flush_events()

	plt.show()

if __name__ == '__main__':
	savedict = dict(save=False, savename='implicit_mesh.jpg',\
					savepath=join("../../", "jpeg_dumps"))
	main(savedict)


from typing import Optional

import numpy as np

from mygrad.operation_base import Operation
from mygrad.tensor_base import Tensor
from mygrad.typing import ArrayLike

class Sigmoid(Operation):
    def __call__(self, a):
        self.variables = (a,)
        x = np.asarray(-1.0 * a.data)
        np.exp(x, out=x)
        x += 1
        np.reciprocal(x, out=x)
        self.sigmoid = x
        return self.sigmoid

    def backward_var(self, grad, index, **kwargs):
        return grad * self.sigmoid * (1.0 - self.sigmoid)

def sigmoid(x: ArrayLike, *, constant: Optional[bool] = None) -> Tensor:
    """Applies the sigmoid activation function::

      f(x) = 1 / (1 + exp(-x))

    Parameters
    ----------
    x : ArrayLike
        sigmoid is applied element-wise on ``x``.

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

    Returns
    -------
    mygrad.Tensor

    Examples
    --------
    >>> import mygrad as mg
    >>> from mygrad.nnet import sigmoid
    >>> x = mg.linspace(-5, 5, 10)
    >>> sigmoid(x)
    Tensor([0.00669285, 0.02005754, 0.0585369 , 0.1588691 , 0.36457644,
        0.63542356, 0.8411309 , 0.9414631 , 0.97994246, 0.99330715])

    .. plot::

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


"""
diffutils

"""

import numpy as np
from scipy.special import factorial
from fractions import Fraction

def lcm_arr(arr):
    """ Calculate least common multiplier for array of integers
    """
    result = np.lcm(arr[0], arr[1])
    for i in range(2, len(arr)-1):
        result = np.lcm(result, arr[i])

    return result

def stencil(evaluation_points, order = 1, h = 1, fraction = False):
    """
    Calculate stencil for finite difference calculation of derivative

    Parameters
    ----------
    evaluation_points: array_like
        evaluation points in regular grid. e.g. [-1, 0, 1] for
        central difference or [-1, 0] for backward difference
    order: integer, optional
        order of the derivative. Default 1 (first order)
    h: scalar, optional
        Step size. Default 1
    fraction: bool, optional
        Set to True to return coefficients as integer numerators
        and a common denomenator. Be careful with this if you use
        a very large number of evaluation points...

    Returns
    -------
    coefficients: array
        array of coefficients in stencil. Unless fraction is set
        to True - in which case a tuple will be returned with
        an array of numerators and an integer denominator. If
        fraction is True, h is ignored - and you should multiply the
        denominator by h**order to get the coefficients

    Note
    ----
    Algorithm from Finte Difference Coefficient Calculator
    (https://web.media.mit.edu/~crtaylor/calculator.html)
    """

    # calculate coefficients:
    evaluation_points = np.array(evaluation_points).flatten().reshape((1, -1))
    p = np.arange(evaluation_points.size).reshape((-1, 1))
    d = np.zeros(evaluation_points.size)
    d[order] = factorial(order)

    coeffs = np.linalg.inv(evaluation_points**p).dot(d)

    if fraction:
        # format nicely:
        fracs = [Fraction(c).limit_denominator() for c in coeffs]
        denominators = [c.denominator for c in fracs]
        numerators   = [c.numerator for c in fracs]
        cd = lcm_arr(denominators)
        numerators = [int(c * cd / a) for (c, a) in zip(numerators, denominators)]
        return (numerators, cd)
    else:
        return coeffs / h ** order


from sympy import *
from difference_quotient import difference_quotient

def newton_interpolate(points: list, N_start=0, points_start=[], simplify_result=True, verbose=False):
    """牛顿插值

    Args:
        points: [(x1, y1), (x2, y2), ..., (xn, yn)]： 插值点

        N_start: a sympy object of Symbol('x'), 起始插值多项式。
        points_start: [(x1, y1), (x2, y2), ..., (xn, yn)]: 计算 N_start 用的插值点
                 该函数中做的插值会「承袭」这个用 points_start 计算的 N_start，在其基础上用新增插值点 points 去改进。
                 default 0 (从头开始构建).

        simplify_result: bool, 化简最终结果, default True
        verbose: 打印出每一步计算差商的值, default False

    Returns:
        N: a sympy object of Symbol('x'), 插值多项式 $N(x)$
    """
    x = Symbol('x')

    # sympify points
    # for i in range(len(points)):
    #     points[i] = sympify(points[i][0]), sympify(points[i][1])

    def f(x): return dict(points + points_start)[x]

    xs = [p[0] for p in points_start]  # 承袭的插值点
    N = N_start   # 承袭的插值多项式
    for point in points:
        xs.append(point[0])
        N += difference_quotient(f, xs, verbose) * \
            prod([x - xi for xi in xs[:-1]])

    if simplify_result:
        N = simplify(N)
    return N

if __name__ == "__main__":
    points = [(11, 0.190809), (12, 0.207912), (13, 0.224951)]

    N = newton_interpolate(points)
    print('插值多项式:', N)
    print('Hypothesis:  ', N.subs(Symbol('x'), 11.5))
    print('Actual vaule:', sin(rad(11.5)).evalf())

    # 承袭之前的 N:
    print('承袭:')
    new_points = [(11.2, sin(rad(11.2)).evalf()),
                  (11.7, sin(rad(11.7)).evalf())]
    N1 = newton_interpolate(new_points, N_start=N,
                            points_start=points, verbose=True)
    print('插值多项式:', N1)
    print('Hypothesis:  ', N1.subs(Symbol('x'), 11.5).evalf())
    print('Actual vaule:', sin(rad(11.5)).evalf())


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

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

def kernel(x, center, width):
    return np.exp(- (x-center)**2 / 2 / width**2)

def expand_feature1(x, mu=None, std=None):
    # 因为只在训练集上计算数据的均值和方差
    # 所以对测试数据调用该函数时，mu 和 std 不能为空，要传入之前在训练集上计算的值
    if mu is None:
        mu = x.mean()
    if std is None:
        std = x.std()
    x1 = (x - mu)/std
    # 因为 sigmoid 函数在自变量过大或过小时会饱和，所以这里先对 x1 归一化再计算 x2
    # 同时这里也没有对 x2 归一化，因为 sigmoid 函数的计算结果在[0, 1]区间，归一化不是十分必要
    x2 = sigmoid(x1)
    return mu, std, np.hstack((np.ones((x.shape[0],1)), x1, x2))

def expand_feature2(x, mu=None, std=None):
    # 任务2：添加一个全'1'的列和根据先验知识（或假设）做特征工程后的列
    # 灵活地根据数据的取值范围决定是否进行归一化
    pass

def expand_feature3(X, C, W):
    return [kernel(X, c, W) for c in C]

def plot_loss(model, n_iter):
    plt.figure()
    plt.semilogy(model.trainloss, 'b-', model.validloss, 'r-')
    plt.xlim(0, n_iter)
    plt.xlabel('iteration')
    plt.ylabel('loss')
    plt.title('learning curve')
    plt.legend(['training loss', 'validation loss'])
    plt.show()


import numpy as np
import matplotlib.pyplot as plt

# Grab the inv function as inverse + log and det
inverse = np.linalg.inv
log = np.math.log
det = np.linalg.det

# Functions to compute the weights
def compute_W(cov_inverse):
    return -(1/2) * cov_inverse

def compute_w(cov_inverse, mean_vector):
    return cov_inverse * mean_vector

def compute_w0(cov, cov_inverse, mean_vector, prior_prob):
    return -(1/2) * mean_vector.T * cov_inverse * mean_vector - (1/2) * log(det(cov)) + log(prior_prob)

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

set_2 = np.array([
    [6, 9],
    [8, 9],
    [9, 8],
    [9, 9],
    [9, 10],
    [8, 11]
])

# Find covariance matrix, inverse and mean
mean_vec1 = np.matrix(np.mean(set_1, axis=0)).T
mean_vec2 = np.matrix(np.mean(set_2, axis=0)).T
cov_set1 = np.cov(set_1.T)
cov_set2 = np.cov(set_2.T)
cov_set1_inverse = inverse(cov_set1)
cov_set2_inverse = inverse(cov_set2)

print("First class mean vector:\n", mean_vec1)
print("Second class mean vector:\n", mean_vec2)

print("First class covariance matrix:\n", cov_set1)
print("Second class covariance matrix:\n", cov_set2)

# Compute the weights of the 1'st discriminator
W1 = compute_W(cov_set1_inverse)
w1 = compute_w(cov_set1_inverse, mean_vec1)
w10 = compute_w0(cov_set1, cov_set1_inverse, mean_vec1, 1/2)

# Compute the weights of the 2'nd discriminator
W2 = compute_W(cov_set2_inverse)
w2 = compute_w(cov_set2_inverse, mean_vec2)
w20 = compute_w0(cov_set2, cov_set2_inverse, mean_vec2, 1/2)

# Print the results
print("The results for the first discriminator: ")
print(W1)
print(w1)
print(w10)

print("The results for the second discriminator: ")
print(W2)
print(w2)
print(w20)

# Plot the discriminator
plt.scatter(set_1[:, 0], set_1[:, 1])
plt.scatter(set_2[:, 0], set_2[:, 1])
x = np.linspace(-10, 35, 80)
y = np.linspace(-10, 35, 80)

xx, yy = np.meshgrid(x, y)
plt.contour(xx, yy, (-0.1)*xx**2 - (0.45)*yy**2 - (6.11)*xx - 8.1*(yy) + 0.96*xx*yy + 67.96)
plt.show()


import numpy as np

class LinerRegressionNE:

    def __init__(self):
        self.theta = None

    @staticmethod
    def normal_equation(x, y):
        # or inv(x.T @ x) @ x.T @ y
        theta = np.linalg.pinv(x)@ y
        return theta

    def fit(self, x, y):
        theta = self.normal_equation(x, y)
        self.theta = theta

    def predict(self, x_test):
        y_predict = np.sum(x_test * self.theta, axis=1)
        return y_predict


import cvxpy as cp

x1 = cp.Variable(1)
x2 = cp.Variable(1)

constraints = [2*x1+x2 >= 1, x1+3*x2 >= 1, x1 >= 0, x2 >= 0]

objectives = [
    cp.Minimize(x1 + x2),
    cp.Minimize(-x1 - x2),
    cp.Minimize(x1),
    cp.Minimize(cp.max_elemwise(x1, x2)),
    cp.Minimize(cp.power(x1, 2) + 9*cp.power(x2, 2))
]

for o_id, objective in enumerate(objectives):
    prob = cp.Problem(objective, constraints)
    print('< Objective', o_id, '>')
    print('Optimal objective value    :', prob.solve())
    print('optimal value for variables: x1={}, x2={}'.format(x1.value, x2.value))
    print('-------------------------------------------------------------------------\n')


import numpy as np

class HMM():
    def __init__(self, transition_prob, emission_prob, initial_state_prob):
        '''
            transition probabilitys : 2d nparray
            emission probabilitys: 2d nparray
            initial state prob: 1d nparray
        '''
        self._transition_prob = transition_prob
        self._emission_prob = emission_prob
        self._initial_state_prob = initial_state_prob
        self._state_num = len(transition_prob)

    def evaluation_by_forward(self, observation):
        '''
            observation:1d nparray
        '''
        state_num = self._state_num
        emission_prob = self._emission_prob
        transition_prob = self._transition_prob
        initial_state_prob = self._initial_state_prob
        max_t = len(observation)
        α = np.zeros((max_t, state_num))
        for t in range(max_t):
            for j in range(state_num):
                if t == 0 :
                    α[t][j] = initial_state_prob[j] * emission_prob[j][observation[t]]
                else:
                    α[t][j] = sum(α[t-1][i] * transition_prob[i][j] for i in range(state_num)) * emission_prob[j][observation[t]]

        return sum(α[max_t-1])

    def decode_by_viterbi_algorithm(self, observation):
        state_num = self._state_num
        emission_prob = self._emission_prob
        transition_prob = self._transition_prob
        initial_state_prob = self._initial_state_prob
        max_t = len(observation)
        δ = np.zeros((max_t, state_num))
        #ψ = np.zeros((max_t, state_num))
        for t in range(max_t):
            for j in range(state_num):
                if t == 0 :
                    δ[t][j] = initial_state_prob[j] * emission_prob[j][observation[t]]
                else:
                    δ[t][j] = max(δ[t-1][i] * transition_prob[i][j] for i in range(state_num)) * emission_prob[j][observation[t]]
                    #ψ[t][j] = np.argmax([δ[t-1][i] * transition_prob[i][j] for i in range(state_num)])

        return [np.argmax([δ[t][i] for i in range(state_num)]) for t in range(max_t)]

transition_prob = np.asarray([[0.6, 0.5, 0.4], [0.2, 0.3, 0.1], [0.2, 0.2, 0.5]])
emission_prob = np.asarray([[0.7, 0.1, 0.2], [0.1, 0.6, 0.3], [0.3, 0.3, 0.4]])
initial_state_prob = np.asarray([0.5, 0.2, 0.3])

model = HMM(transition_prob, emission_prob, initial_state_prob)

observation = np.asarray([0, 0, 2, 1, 2, 1, 0])
print(model.evaluation_by_forward(observation))
print(model.decode_by_viterbi_algorithm(observation))
'''
double backward(int* o, int T)
{
    for (int t=T-1; t>=0; --t)
        for (int i=0; i<N; ++i)
            if (t == T-1)
                β[t][i] = 1.0;
            else
            {
                double p = 0;
                for (int j=0; j<N; ++j)
                    p += a[i][j] * b[j][o[t+1]] * β[t+1][j];
                β[t][i] = p;
            }

    double p = 0;
    for (int j=0; j<N; ++j)
        p += π[j] * b[j][o[0]] * β[0][j];
    return p;
}
'''


import numpy as np
import load_mnist
import warnings

'''
Weights are assumed to be modified to incorporate bias
ie. X = 1 + x0 + x1 + ...
'''
# weights = 1 x (n + 1) , X = m x (n + 1)

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

def predict(weights, X):
	# print("Product ================")

	prediction = sigmoid(X @ weights.T)
	assert all(prediction <= 1)
	return prediction

def cost(weights, X, y):
	pred = predict(weights, X)
	s1 = y * np.log(pred)
	s2 = (1 - y) * np.log(1 - pred)

	return -np.sum(s1 + s2)

def compute_gradients(weights, X, y):
	weights_n = (predict(weights, X) - y).T @  X
	return weights_n

def learn_weights(X, y, rate= 4e-5, iters=1000, thresh=0.1):
	weights = np.random.uniform(low=1e-4, high=1e-6, size=(1,X.shape[1]))

	for _ in range(iters):
		grad = compute_gradients(weights, X, y)
		weights_n = weights - rate * grad
		c_old = cost(weights, X, y)
		c_new = cost(weights_n, X, y)

		print("Iteration : %d , Old cost = %f , New cost = %f" % (_, c_old, c_new))

		if abs(c_old - c_new) < thresh:
			break

		weights = weights_n

	return weights

def train_test_split(num=5):

	train_img    = load_mnist.read_idx('train-img.data')
	train_labels = load_mnist.read_idx('train-labels.data')
	test_img 	 = load_mnist.read_idx('test-img.data')
	test_labels  = load_mnist.read_idx('test-labels.data')

	train_img = np.reshape(train_img, (train_img.shape[0], -1))
	test_img  = np.reshape(test_img, (test_img.shape[0], -1))

	# normalize the data https://stackoverflow.com/questions/35419882/cost-function-in-logistic-regression-gives-nan-as-a-result

	mu = np.mean(train_img, 0)
	sig = np.std(train_img, 0)
	train_img = np.nan_to_num((train_img - mu) / sig)
	test_img  = np.nan_to_num((test_img - mu) / sig)

	X_train = train_img[train_labels == num]
	X_test  = test_img[test_labels == num]

	l_train = X_train.shape[0]
	l_test  = X_test.shape[0]

	X_train_extra = train_img[train_labels != num][:l_train, :]
	X_test_extra  = test_img[test_labels != num][:l_test, :]

	X_train =  np.append(X_train, X_train_extra, axis=0)
	X_test  =  np.append(X_test, X_test_extra, axis=0)

	print("X_train : %s , X_test : %s " % (X_train.shape, X_test.shape))

	y_train = np.array([1] * l_train + [0] * l_train).reshape(2 * l_train, 1)
	y_test  = np.array([1] * l_test  + [0] * l_test).reshape(2 * l_test, 1)

	print("y_train : %s , y_test : %s " % (y_train.shape, y_test.shape))

	return (X_train, y_train, X_test, y_test)

def check_accuracy(X, y, weights, thresh=0.5):
	pred = predict(weights, X)
	# pred[pred >= thresh] = 1
	# pred[pred <  thresh] = 0
	pred = pred >= thresh	# need to check this !!
	return sum(np.logical_not(np.logical_xor(pred, y))) / len(y)

def main():

	X_train, y_train, X_test, y_test = train_test_split()
	X_train = np.append(X_train, np.ones((X_train.shape[0], 1)), axis=1)
	X_test  = np.append(X_test, np.ones((X_test.shape[0], 1)), axis=1)

	# print("X_train : %s , X_test : %s " % (X_train[0, X_test.shape))

	print("Learning weights ...")
	w = learn_weights(X_train, y_train)
	# print("Weights learned : %s!" % w)
	# print(X_test[0])
	# print(X_test @ w.T)
	print("Accuracy in test set = %f" % check_accuracy(X_test, y_test, w))

main()


#Plotting the first five Taylor approximations for e^x at x = 1
#I am currently taking a calculus course through Coursera, so I can't guarantee that the math below is correct! However, my answer lines up with that found at https://www.symbolab.com/solver/taylor-maclaurin-series-calculator/taylor%20e%5E%7Bx%7D%2C%201
#Kenneth Burchfiel--first version published on 2021-1-30
import matplotlib.pyplot as plt
import numpy as np
xset = np.arange(-1,3,0.01) #x coordinates. Graph is centered at x = 1
e_x = np.exp(xset) #e^x, the function we are trying to approximate through the Taylor series. xset is synonymous with x
plt.axhline(y=np.exp(1)) #Graphs a horizontal line at e = 1. 0th approximation
first_approximation = np.exp(1) + np.exp(1)*(xset-1) #Each approximation in the series is built up of the previous approximation plus a new expression
second_approximation = np.exp(1) + np.exp(1)*(xset-1) + (np.exp(1))*((xset-1)**2)/2
third_approximation = np.exp(1) + np.exp(1)*(xset-1) + (np.exp(1))*((xset-1)**2)/2 + (np.exp(1))*((xset-1)**3)/6
fourth_approximation = np.exp(1) + np.exp(1)*(xset-1) + (np.exp(1))*((xset-1)**2)/2 + (np.exp(1))*((xset-1)**3)/6 + (np.exp(1))*((xset-1)**4)/24
plt.plot(xset,e_x)
plt.plot(xset,first_approximation)
plt.plot(xset,second_approximation)
plt.plot(xset,third_approximation)
plt.plot(xset,fourth_approximation)
plt.show() #The plot shows that each approximation equals e^x at x=1, but then diverges from e^x to the left and right of x=1.


import matplotlib.pyplot as plt
from math import sin, cos
import numpy as np

def interpolate(a0, a1, w):
    return (a1 - a0) * w + a0

def random(ix, iy):
    r = 2920 * sin(ix * 21942 + iy * 171324 + 8912) * cos(ix * 23157 * iy * 217832 + 9758)
    return (cos(r), sin(r))

def dot(ix, iy, x, y):
    r = random(ix, iy)
    dx = x - float(ix)
    dy = y - float(iy)
    return (dx*r[0] + dy*r[1])

def perlin(x,y,scale=1):
    x0, y0 = int(x), int(y)
    x1 = x0 + 1
    y1 = y0 + 1

    sx = x - x0
    sy = y - y0

    n0 = dot(x0, y0, x, y)
    n1 = dot(x1, y0, x, y)
    ix0 = interpolate(n0, n1, sx)

    n0 = dot(x0, y1, x, y)
    n1 = dot(x1, y1, x, y)
    ix1 = interpolate(n0, n1, sx)

    val = interpolate(ix0, ix1, sy)
    return val * scale

dT = 0.1
start = 0
end = 300
T = np.arange(start, end, dT)
P = np.array([perlin(x,1) for x in T])

fig, ax = plt.subplots()
ax.plot(T,P)
ax.set_title(f'[ dT: {dT} | start: {start} | end: {end} ]')
ax.set_xlabel('x')
ax.set_ylabel('value')
plt.show()


from scipy.special import gamma, airy
def func(y, t):
    return [t*y[1], y[0]]
def gradient(y, t):
    return [[0,t], [1,0]]
x = np.arange(0, 4.0, 0.01)
y_0 = [-1.0 / 3**(1.0/3.0) / gamma(1.0/3.0), 1.0 / 3**(2.0/3.0) / gamma(2.0/3.0)]
Ai, Aip, Bi, Bip = airy(x)
y = odeint(func, y_0, x, rtol=1e-12, atol=1e-12, Dfun=gradient) # Exact answer: (Aip, Ai)

example_snippets/multimenus_snippets/Snippets/SciPy/Integration and ODE solvers/Numerically integrate ODE systems/General integration of ordinary differential equations with known gradient.py


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Fri Feb 21 18:16:57 2020

@author: linux-asd
"""

import numpy as np

def Rx(roll):
    """ Rotation matrix arround x (roll)
    """
#    roll = np.radians(roll)
    return np.matrix([[1,            0,             0, 0],
                      [0, np.cos(roll), -np.sin(roll), 0],
                      [0, np.sin(roll),  np.cos(roll), 0],
                      [0,            0,             0, 1]])

def Ry(pitch):
    """ Rotation matrix arround y (pitch)
    """
#    pitch = np.radians(pitch)
    return np.matrix([[ np.cos(pitch), 0, np.sin(pitch), 0],
                      [             0, 1,             0, 0],
                      [-np.sin(pitch), 0, np.cos(pitch), 0],
                      [             0, 0,             0, 1]])

def Rz(yaw):
    """ Rotation matrix arround z (yaw)
    """
#    yaw = np.radians(yaw)
    return np.matrix([[np.cos(yaw), -np.sin(yaw), 0, 0],
                      [np.sin(yaw),  np.cos(yaw), 0, 0],
                      [          0,            0, 1, 0],
                      [          0,            0, 0, 1]])

def Rxyz(roll , pitch , yaw):
    if roll != 0 or pitch != 0 or yaw != 0:
        R = Rx(roll)*Ry(pitch)*Rz(yaw)
        return R
    else:
        return np.identity(4)

def RTmatrix(orientation, position):
    """compose translation and rotation"""
    roll = orientation[0]
    pitch = orientation[1]
    yaw = orientation[2]
    x0 = position[0]
    y0 = position[1]
    z0 = position[2]

    translation = np.matrix([[1, 0, 0, x0],#Translation matrix
                             [0, 1, 0, y0],
                             [0, 0, 1, z0],
                             [0, 0, 0,  1]])
    rotation = Rxyz(roll, pitch, yaw)#rotation matrix

    return rotation*translation

def transform(coord,rotation,translation):
    """transforms a vector to a desire rotation and translation"""
    vector = np.array([[coord[0]],
                       [coord[1]],
                       [coord[2]],
                       [      1]])

    tranformVector = RTmatrix(rotation,translation)*vector
    return np.array([tranformVector[0,0], tranformVector[1,0], tranformVector[2,0]])


import numpy

def functional_iteration(f, x0, max_steps=100, tol=1e-10):
    x = numpy.zeros(max_steps+1)
    x[0] = x0
    step = 0
    g = lambda x : x - f(x)
    while abs(f(x[step])) > tol and step < max_steps:
        step = step + 1
        x[step] = g(x[step-1])
    return x[:step+1]

if __name__=="__main__":
    def F(x):
        return 1/2*x**2 - 1/52*x**4 - 72/52*x
    def dF(x, dx):
        return (F(x+dx) - F(x)) / dx

    f_1em6 = lambda x : dF(x, 1e-6)
    x_df_6 = functional_iteration(f_1em6, 1)
    print("Root: ", x_df_6[-1], "iterations", len(x_df_6))
    f_1em1 = lambda x : dF(x, 1e-1)
    x_df_1 = functional_iteration(f_1em1, 1)
    print("Root: ", x_df_1[-1], "iterations", len(x_df_1))
    f_5em1 = lambda x : dF(x, 5e-1)
    x_df_5 = functional_iteration(f_5em1, 1)
    print("Root: ", x_df_5[-1], "iterations", len(x_df_5))


import numpy as np

def sphere_vol_to_r(v):
    """Finds radius from a sphere's volume

    returns radius of sphere
    """
    return (3*v/(4*np.pi))**(1/3)

def cube_vol_to_r(v):
    """Calculates cube radius from it's volume

    returns radius of cube
    """
    return np.cbrt(v)

def calculate_delta(D, dt):
    """Calculates appropriate step-size for a diffusion coefficient

    returns the step-size for a random-walk particle to take per dt
    """
    return np.sqrt(6*D*dt)

def calculate_opt_dt(a, D):
    """Calculates the optimal dt based on size of pore
    and diffusion coefficent

    returns a value for dt
    """
    return (a*1e-3) / (6*D)


from itertools import combinations_with_replacement

import numpy as np

def shuffle_data(X, y, seed=None):
    """ Random shuffle of the samples in X and y """
    if seed:
        np.random.seed(seed)
    idx = np.arange(X.shape[0])
    np.random.shuffle(idx)
    return X[idx], y[idx]

def normalize(X, axis=-1, order=2):
    """ Normalize the dataset X """
    l2 = np.atleast_1d(np.linalg.norm(X, order, axis))
    l2[l2 == 0] = 1
    return X / np.expand_dims(l2, axis)

def polynomial_features(X, degree):
    """ Make polynomial feature.
    Parameters:
    -----------
    X: ndarray of shape (n_samples, n_features)
        The input samples
    degree: int
        The highest of the degrees of the polynomial's monomials (individual terms) with non-zero coefficients
    Returns:
    -----------
    X_new: ndarray of shape (n_samples, n_output_features)
        New feature matrix consisting of all polynomial combinations of the features with degree less than or equal to the specified degree. For example, if an input sample is two dimensional and of the form [a, b], the degree-2 polynomial features are [1, a, b, a^2, ab, b^2].

    """
    n_samples, n_features = np.shape(X)

    def index_combinations():
        combs = [
            combinations_with_replacement(range(n_features), i)
            for i in range(0, degree + 1)
        ]
        flat_combs = [item for sublist in combs for item in sublist]
        return flat_combs

    combinations = index_combinations()
    n_output_features = len(combinations)
    X_new = np.empty((n_samples, n_output_features))

    for i, index_combs in enumerate(combinations):
        X_new[:, i] = np.prod(X[:, index_combs], axis=1)

    return X_new

def k_fold_cross_validation_sets(X, y, n_fold, shuffle=True, seed=None):
    """ Split the data into train and test sets """
    if shuffle:
        X, y = shuffle_data(X, y, seed)

    n_samples = len(y)
    left_overs = {}
    n_left_overs = n_samples % n_fold
    if n_left_overs != 0:
        left_overs["X"] = X[-n_left_overs:]
        left_overs["y"] = y[-n_left_overs:]
        X = X[:-n_left_overs]
        y = y[:-n_left_overs]

    X_split = np.split(X, n_fold)
    y_split = np.split(y, n_fold)
    sets = []
    for i in range(n_fold):
        # Use the i-th fold for testing
        X_test, y_test = X_split[i], y_split[i]
        # Train on the rest
        X_train = np.concatenate(X_split[:i] + X_split[i + 1:], axis=0)
        y_train = np.concatenate(y_split[:i] + y_split[i + 1:], axis=0)
        sets.append([X_train, X_test, y_train, y_test])

    # Add left over samples to last set as training samples
    if n_left_overs != 0:
        np.append(sets[-1][0], left_overs["X"], axis=0)
        np.append(sets[-1][2], left_overs["y"], axis=0)

    return np.array(sets, dtype=object)

def train_test_split(X, y, test_size=0.5, shuffle=True, seed=None):
    """ Split the data into train and test sets """
    if shuffle:
        X, y = shuffle_data(X, y, seed)
    # Split the training data from test data in the ratio specified in
    # test_size
    split_i = int(len(y) * (1 - test_size))
    X_train, X_test = X[:split_i], X[split_i:]
    y_train, y_test = y[:split_i], y[split_i:]

    return X_train, X_test, y_train, y_test

def mean_squared_error(y_true, y_pred):
    """ Returns the mean squared error between y_pred and y_true """
    mse = np.mean((y_true - y_pred)**2)
    return mse


import numpy as np

list1 = [0,1,2,3,4]

arr1d = np.array(list1)

list1.append(5)

arr1d + 2

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

type(arr2d)

arr2d.dtype

arr2d = np.array(list2, dtype="float")

arr2d = arr2d.astype('int')

arr2d.astype('str')

list1.append('6')

np2list = arr2d.tolist()

arr2d.tostring()

arr2d.tobytes()

# dtypes and shape

arr2d = arr2d.astype('float')

print("Shape: ",arr2d.shape)

arr2d.size

arr2d.ndim

arr1d = arr1d * arr1d

arr1d[1]

arr2d[1][0]

boolarr = arr2d < 3

arr2d[boolarr]

arr2d[::-1]

# np.nan, np.inf

arr2d[0][0] = np.nan

arr2d[0][1] = np.inf

np.isnan(arr2d)

np.isinf(arr2d)

missing_flag = np.isnan(arr2d) | np.isinf(arr2d)

# replace inf and nan with 0

arr2d[missing_flag]

arr2d[missing_flag] = 0

# Statistical operations

arr2d.mean()

arr2d.max()

arr2d.min()

arr2d.all()

arr2d.std()

arr2d.var()

arr2d.squeeze()

arr2d.cumsum()

arr = arr2d[:2,:2]

arr2d[1:3,1:3]

arr2d.reshape(9,1)

arr2d.reshape(1,9)

a = arr2d.flatten()

b = arr2d.ravel()

b[0] = -1

# sequence, repetitions and random numbers

np.arange(1,5)

np.arange(1,5, dtype='int')

np.arange(2,50,2)

np.linspace(1,50,100)

np.logspace(1,50,10)

np.zeros([2,2])

np.ones([2,2])

a = [1,2,3]

np.tile(a,3)

np.repeat(a,3)

np.repeat(arr2d,3)

# random number

np.random.rand(1,3)

np.random.randn(1,3)

np.random.randint(0,10,[3,3])

np.random.seed(0)
np.random.randint(0,10,[3,3])

np.unique(arr2d)

uniques, counts = np.unique(arr2d,return_counts=True)

uniques

counts

# more

arr = np.array([8,94,8,56,1,3,4,5,7])

index_gt10 = np.where(arr>10)

arr[index_gt10]

arr[arr>10]

arr>10

np.where(arr>10,'gt10','lt5')

arr.argmax()

arr.argmin()

# read and write csv file

data = np.genfromtxt("https://raw.githubusercontent.com/selva86/datasets/master/Auto.csv",delimiter=",",skip_header=1,filling_values=-1000,dtype="float")

data.shape
np.set_printoptions(suppress=True)
data[:3]

data2 = np.genfromtxt("https://raw.githubusercontent.com/selva86/datasets/master/Auto.csv", delimiter=",",skip_header=1,dtype=None)
data2[:3]

np.savetxt('data.csv',data,delimiter=',')
np.save('data.npy',data)
np.savez('data.npz',data,data2)

d = np.load('data.npy')

d2 = np.load('data.npz')

d2.files

d2['arr_1']

# concat wih rows and col wise

arr1 = np.zeros([4,4])
arr2 = np.ones([4,4])

# ver
np.concatenate([arr1,arr2],axis=0)
np.vstack([arr1,arr2])
np.r_[arr1,arr2]

#hor
np.concatenate([arr1,arr2],axis=1)

np.hstack([arr1,arr2])

np.c_[arr1,arr2]

# sort a numpy array

arr = np.random.randint(1,10,size=[10,5])

np.sort(arr,axis=0)

sorted_index = arr[:,0].argsort()

arr[sorted_index]

# working with dates

d = np.datetime64('2019-06-02 23:10:00')

d

d+1

d+1000

oneday = np.timedelta64(1,'D')

oneminute = np.timedelta64(1,'m')

dates = np.arange(np.datetime64('2019-06-02'),np.datetime64('2020-06-02'))

# Advance function

def foo(x):
    if x%2==1:
        return x**2
    else:
        return x/2

foo(10)

foo_v = np.vectorize(foo,otypes=[float])

foo_v(arr)


# Scaling and Normalization
# modules we'll use
import pandas as pd
import numpy as np

# for Box-Cox Transformation
from scipy import stats

# for min_max scaling
from mlxtend.preprocessing import minmax_scaling

# plotting modules
import seaborn as sns
import matplotlib.pyplot as plt

# read in all our data
kickstarters_2017 = pd.read_csv("../input/kickstarter-projects/ks-projects-201801.csv")

# set seed for reproducibility
np.random.seed(0)

# select the usd_goal_real column
original_data = pd.DataFrame(kickstarters_2017.usd_goal_real)

# scale the goals from 0 to 1
scaled_data = minmax_scaling(original_data, columns=['usd_goal_real'])

print('Original data\nPreview:\n', original_data.head())
print('Minimum value:', float(original_data.min()),
      '\nMaximum value:', float(original_data.max()))
print('_'*30)

print('\nScaled data\nPreview:\n', scaled_data.head())
print('Minimum value:', float(scaled_data.min()),
      '\nMaximum value:', float(scaled_data.max()))

# select the usd_goal_real column
original_goal_data = pd.DataFrame(kickstarters_2017.goal)

scaled_goal_data = minmax_scaling(original_goal_data, columns=['goal'])

# get the index of all positive pledges (Box-Cox only takes positive values)
index_of_positive_pledges = kickstarters_2017.usd_pledged_real > 0

# get only positive pledges (using their indexes)
positive_pledges = kickstarters_2017.usd_pledged_real.loc[index_of_positive_pledges]

# normalize the pledges (w/ Box-Cox)
normalized_pledges = pd.Series(stats.boxcox(positive_pledges)[0],
                               name='usd_pledged_real', index=positive_pledges.index)

print('Original data\nPreview:\n', positive_pledges.head())
print('Minimum value:', float(positive_pledges.min()),
      '\nMaximum value:', float(positive_pledges.max()))
print('_'*30)

print('\nNormalized data\nPreview:\n', normalized_pledges.head())
print('Minimum value:', float(normalized_pledges.min()),
      '\nMaximum value:', float(normalized_pledges.max()))

# plot normalized data
ax = sns.histplot(normalized_pledges, kde=True)
ax.set_title("Normalized data")
plt.show()

# get the index of all positive pledges (Box-Cox only takes positive values)
index_positive_pledges = kickstarters_2017.pledged > 0

# get only positive pledges (using their indexes)
positive_pledges_only = kickstarters_2017.pledged.loc[index_positive_pledges]

# normalize the pledges (w/ Box-Cox)
normalized_values = pd.Series(stats.boxcox(positive_pledges_only)[0],
                              name='pledged', index=positive_pledges_only.index)

# plot normalized data
ax = sns.histplot(normalized_values, kde=True)
ax.set_title("Normalized data")


'''
    Problem 78 - Coin partitions

    Let p(n) represent the number of different ways in which n coins can be separated into piles.
    For example, five coins can be separated into piles in exactly seven different ways, so p(5)=7.

    Find the least value of n for which p(n) is divisible by one million.
'''
import numpy as np
from numba import jit

@jit
def solve(n, m):
    res = 0
    a = np.ones(n + 1).astype(np.uint32)
    b = np.ones(n + 1).astype(np.uint32)

    for i in range(2, n + 1):
        for j in range(1, n + 1):
            if j < i:
                b[j] = a[j]
            else:
                b[j] = (a[j] + b[j - i]) % m

        if b[i] % m == 0:
            res = i
            break

        a = b.copy()
        b = np.ones(n + 1).astype(np.uint32)

    return res

if __name__ == "__main__":
    lim = 100000
    print(solve(lim, 10**6))
    # print(solve(lim,10**6))


#!/usr/bin/python

import scipy.io
import numpy as np
from scipy.spatial.distance import pdist, squareform, cdist
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from numpy.linalg import inv, norm
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter

#Load the data from the file
DATA = scipy.io.loadmat('ASSIGNMENT1.mat')
data = DATA['DATA']

#Split the data into training and test sets
samples = len(data)
#Shuffle the data randomly
np.random.shuffle(data)
#Split into test and train
training, test = data[0:2500,:], data[2500:,:]

#Plot the training data
fig = plt.figure()
ax = fig.add_subplot(121, projection='3d')
ax.set_title('Scatter plot of Z1')
ax.scatter(training[:,0], training[:,1], training[:,2])
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z1')

ax2 = fig.add_subplot(122, projection='3d')
ax2.scatter(training[:,0], training[:,1], training[:,3])
ax2.set_title('Scatter Plot of Z2')
ax2.set_xlabel('X')
ax2.set_ylabel('Y')
ax2.set_zlabel('Z2')

#Using Regularized regression
#Get data and append column of ones to the left
X = np.concatenate((np.ones((training.shape[0],1)), training[:,0:2]), axis=1)
#Get the target vectors
t1 = training[:,2]
t2 = training[:,3]
#Regularization paramater lambda
l = 1.

#Use sine and cosine basis functions here
#5 Features in total
PHI = np.vstack((X[:,0], np.sin(2*np.pi*X[:,1]), np.cos(2*np.pi*X[:,1]),
                 np.sin(2*np.pi*2.5*X[:,2]), np.cos(2*np.pi*2.5*X[:,2])))

#Use Formula for regularized regression to get optimal W
#W = (PHI'*PHI + lambda*I)^-1 *PHI' t
W1 = np.dot(t1, np.dot(inv(np.dot(PHI.T, PHI) + l*np.identity(PHI.shape[1])), PHI.T))
W2 = np.dot(t2, np.dot(inv(np.dot(PHI.T, PHI) + l*np.identity(PHI.shape[1])), PHI.T))

#Print the values of W
print("Using regularized regression")
print(W1, W2)

#Plot the best fit function to check
Xv, Yv = np.meshgrid(np.arange(0,1,0.01), np.arange(0,1,0.01))

Z1_cap = W1[0] + W1[1]*np.sin(2*np.pi*Xv) + W1[2]*np.cos(2*np.pi*2.5*Xv) +\
         W1[3]*np.sin(2*np.pi*2.5*Yv) + W1[4]*np.cos(2*np.pi*2.5*Yv)
#Z1_cap = W1[0] + W1[1]*Xv + W1[2]*Yv + W1[3]*Xv**2 + W1[4]*Yv**2 + W1[5]*Xv**3 + W1[6]*Yv**3
Z2_cap = W2[0] + W2[1]*np.sin(2*np.pi*Xv) + W2[2]*np.cos(2*np.pi*Xv) +\
         W2[3]*np.sin(2*np.pi*2.5*Yv) + W2[4]*np.cos(2*np.pi*2.5*Yv)

fig2 = plt.figure()
ax3 = fig2.gca(projection='3d')
surf = ax3.plot_surface(Xv, Yv, Z1_cap, rstride=1, cstride=1, cmap=cm.coolwarm,
                       linewidth=0, antialiased=False)
fig2.colorbar(surf, shrink=0.5, aspect=5)
ax3.set_title('Regularized Regression')
ax3.set_xlabel('X1')
ax3.set_ylabel('Y1')
ax3.set_zlabel('Z1 prediction')

fig3 = plt.figure()
ax4 = fig3.gca(projection='3d')
surf = ax4.plot_surface(Xv, Yv, Z2_cap, rstride=1, cstride=1, cmap=cm.coolwarm,
                        linewidth=0, antialiased=True)
fig3.colorbar(surf, shrink=0.5, aspect=5)
ax4.set_title('Regularized Regression')
ax4.set_xlabel('X1')
ax4.set_ylabel('Y1')
ax4.set_zlabel('Z2 prediction')

#Using kernel methods
print("Using kernel Methods")
l2 = 10
s = 0.07
#Calculate the Gram matrix
pairwise_dists = squareform(pdist(X[:,1:], 'euclidean'))
K = scipy.exp(-(pairwise_dists)** 2 / s ** 2)
print(K.shape)

#Calculate the vector a
a1 = np.dot(inv(K + l2*np.identity(X.shape[0])), t1)
a2 = np.dot(inv(K + l2*np.identity(X.shape[0])), t2)

#Calculate the predictions for Z
#Get the coordinate grid
Xv = np.linspace(0,1,50)
Yv = np.linspace(0,1,50)
Xv, Yv = np.meshgrid(Xv,Yv)
#Unroll the grid of coordinates
coords = np.vstack((Xv.flatten(), Yv.flatten())).T
print("coords shape: "+str(coords.shape))
#Calculate the kernel matrix by calculating pairwise distances
kernel_matrix = scipy.exp(-(cdist(coords, X[:,1:], 'euclidean'))**2/s**2)

print("kernel shape: "+str(kernel_matrix.shape))

#Calculate the predicted Z values and reshape into a grid for plotting.
Z1_preds = np.reshape(np.dot(kernel_matrix, a1), (50,50))
Z2_preds = np.reshape(np.dot(kernel_matrix, a2), (50,50))

#Plot the predictions for kernel regression
fig4 = plt.figure()
ax5 = fig4.gca(projection='3d')
surf = ax5.plot_surface(Xv, Yv, Z1_preds, rstride=1, cstride=1, cmap=cm.coolwarm,
                        linewidth=0, antialiased=True)
fig4.colorbar(surf, shrink=0.5, aspect=5)
ax5.set_title('Kernel Regression Using Gaussian Kernel')
ax5.set_xlabel('X1')
ax5.set_ylabel('Y1')
ax5.set_zlabel('Z1 prediction')

fig5 = plt.figure()
ax6 = fig5.gca(projection='3d')
surf2 = ax6.plot_surface(Xv, Yv, Z2_preds, rstride=1, cstride=1, cmap=cm.coolwarm,
                         linewidth=0, antialiased=True)
fig5.colorbar(surf, shrink=0.5, aspect=5)
ax6.set_title('Kernel Regression Using Gaussian Kernel')
ax6.set_xlabel('X1')
ax6.set_ylabel('Y1')
ax6.set_zlabel('Z2 prediction')

#Sigmoid kernel

plt.show()

import numpy,from numpy,import scipy,from scipy


import math
import numpy as np
import matplotlib.pyplot as plt # for plotting stuff
from random import seed, shuffle
from scipy.stats import multivariate_normal # generating synthetic data
SEED = 1122334455
seed(SEED) # set the random seed so that the random permutations can be reproduced again
np.random.seed(SEED)

def generate_synthetic_data(plot_data=False):

    """
        Code for generating the synthetic data.
        We will have two non-sensitive features and one sensitive feature.
        A sensitive feature value of 0.0 means the example is considered to be in protected group (e.g., female) and 1.0 means it's in non-protected group (e.g., male).
    """

    n_samples = 1000 # generate these many data points per class
    disc_factor = math.pi / 4.0 # this variable determines the initial discrimination in the data -- decraese it to generate more discrimination

    def gen_gaussian(mean_in, cov_in, class_label):
        nv = multivariate_normal(mean = mean_in, cov = cov_in)
        X = nv.rvs(n_samples)
        y = np.ones(n_samples, dtype=float) * class_label
        return nv,X,y

    """ Generate the non-sensitive features randomly """
    # We will generate one gaussian cluster for each class
    mu1, sigma1 = [2, 2], [[5, 1], [1, 5]]
    mu2, sigma2 = [-2,-2], [[10, 1], [1, 3]]
    nv1, X1, y1 = gen_gaussian(mu1, sigma1, 1) # positive class
    nv2, X2, y2 = gen_gaussian(mu2, sigma2, -1) # negative class

    # join the posisitve and negative class clusters
    X = np.vstack((X1, X2))
    y = np.hstack((y1, y2))

    # shuffle the data
    perm = range(0,n_samples*2)
    shuffle(perm)
    X = X[perm]
    y = y[perm]

    rotation_mult = np.array([[math.cos(disc_factor), -math.sin(disc_factor)], [math.sin(disc_factor), math.cos(disc_factor)]])
    X_aux = np.dot(X, rotation_mult)

    """ Generate the sensitive feature here """
    x_control = [] # this array holds the sensitive feature value
    for i in range (0, len(X)):
        x = X_aux[i]

        # probability for each cluster that the point belongs to it
        p1 = nv1.pdf(x)
        p2 = nv2.pdf(x)

        # normalize the probabilities from 0 to 1
        s = p1+p2
        p1 = p1/s
        p2 = p2/s

        r = np.random.uniform() # generate a random number from 0 to 1

        if r < p1: # the first cluster is the positive class
            x_control.append(1.0) # 1.0 means its male
        else:
            x_control.append(0.0) # 0.0 -> female

    x_control = np.array(x_control)

    """ Show the data """
    if plot_data:
        num_to_draw = 200 # we will only draw a small number of points to avoid clutter
        x_draw = X[:num_to_draw]
        y_draw = y[:num_to_draw]
        x_control_draw = x_control[:num_to_draw]

        X_s_0 = x_draw[x_control_draw == 0.0]
        X_s_1 = x_draw[x_control_draw == 1.0]
        y_s_0 = y_draw[x_control_draw == 0.0]
        y_s_1 = y_draw[x_control_draw == 1.0]
        plt.scatter(X_s_0[y_s_0==1.0][:, 0], X_s_0[y_s_0==1.0][:, 1], color='green', marker='x', s=30, linewidth=1.5, label= "Prot. +ve")
        plt.scatter(X_s_0[y_s_0==-1.0][:, 0], X_s_0[y_s_0==-1.0][:, 1], color='red', marker='x', s=30, linewidth=1.5, label = "Prot. -ve")
        plt.scatter(X_s_1[y_s_1==1.0][:, 0], X_s_1[y_s_1==1.0][:, 1], color='green', marker='o', facecolors='none', s=30, label = "Non-prot. +ve")
        plt.scatter(X_s_1[y_s_1==-1.0][:, 0], X_s_1[y_s_1==-1.0][:, 1], color='red', marker='o', facecolors='none', s=30, label = "Non-prot. -ve")

        plt.tick_params(axis='x', which='both', bottom='off', top='off', labelbottom='off') # dont need the ticks to see the data distribution
        plt.tick_params(axis='y', which='both', left='off', right='off', labelleft='off')
        plt.legend(loc=2, fontsize=15)
        plt.xlim((-15,10))
        plt.ylim((-10,15))
        plt.savefig("img/data.png")
        plt.show()

    x_control = {"s1": x_control} # all the sensitive features are stored in a dictionary
    return X,y,x_control


import numpy as np

def normalize_angle(r):
    """
    Parameters:
    ----------
    r: float
        angle (radian)

    Returns:
    ----------
    float
        angle between -pi and +pi
    """

    return np.mod(r + np.pi, 2.0 * np.pi) - np.pi

def normalize_min_max(x, axis=None):
    """
    Parameters:
    ----------
    x: np.array()
        target array
    axis: int
        target axis

    Returns:
    ----------
    np.array()
        normalized array so that the maximum value is 1 and the minimum value is 0
    """

    min = x.min(axis=axis, keepdims=True)
    max = x.max(axis=axis, keepdims=True)
    if max - min == 0:
        return np.full_like(x, 1.0)
    else:
        return (x - min) / (max - min)


import sys
import numpy as np
import csv

import argparse
import logging
import os

from scipy.integrate import odeint

# The gravitational acceleration (m.s-2).
g = 9.81
DEFAULT_RESOLUTION = 5
DEFAULT_DT = 0.01
DEFAULT_TMAX = 30

def deriv(y, t, L1, L2, m1, m2):
    """Return the first derivatives of y = theta1, z1, theta2, z2."""
    theta1, z1, theta2, z2 = y

    c, s = np.cos(theta1-theta2), np.sin(theta1-theta2)

    theta1dot = z1
    z1dot = (m2*g*np.sin(theta2)*c - m2*s*(L1*z1**2*c + L2*z2**2) -
             (m1+m2)*g*np.sin(theta1)) / L1 / (m1 + m2*s**2)
    theta2dot = z2
    z2dot = ((m1+m2)*(L1*z1**2*s - g*np.sin(theta2) + g*np.sin(theta1)*c) +
             m2*L2*z2**2*s*c) / L2 / (m1 + m2*s**2)
    return theta1dot, z1dot, theta2dot, z2dot

def solve(L1, L2, m1, m2, tmax, dt, y0):
    t = np.arange(0, tmax+dt, dt)

    # Do the numerical integration of the equations of motion
    y = odeint(deriv, y0, t, args=(L1, L2, m1, m2))
    theta1, theta2 = y[:,0], y[:,2]

    # Convert to Cartesian coordinates of the two bob positions.
    x1 = L1 * np.sin(theta1)
    y1 = -L1 * np.cos(theta1)
    x2 = x1 + L2 * np.sin(theta2)
    y2 = y1 - L2 * np.cos(theta2)

    return theta1, theta2, x1, y1, x2, y2

def simulate_pendulum(theta_resolution, datafile, tmax, dt):
    # Pendulum rod lengths (m), bob masses (kg).
    L1, L2 = 1.0, 1.0
    m1, m2 = 1.0, 1.0

    # Maximum time, time point spacings (all in s).
    #tmax, dt = 30.0, 0.01

    with open(datafile, 'w') as csvfile:
        writer = csv.writer(csvfile)
        writer.writerow(['theta1_init', 'theta2_init', 'theta1', 'theta2', 'x1', 'y1', 'x2', 'y2'])

        for theta1_init in np.linspace(0, 2*np.pi, theta_resolution):
            for theta2_init in np.linspace(0, 2*np.pi, theta_resolution):
                # Initial conditions: theta1, dtheta1/dt, theta2, dtheta2/dt.
                y0 = np.array([
                    theta1_init,
                    0.0,
                    theta2_init,
                    0.0
                ])

                theta1, theta2, x1, y1, x2, y2 = solve(L1, L2, m1, m2, tmax, dt, y0)
                writer.writerow([theta1_init, theta2_init, theta1[-1], theta2[-1], x1[-1], y1[-1], x2[-1], y2[-1]])

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument(
        'data_file',
        help="Data file where results are saved"
    )

    parser.add_argument(
        '-r',
        '--resolution',
        metavar='NUM',
        type=int,
        default=DEFAULT_RESOLUTION,
        help="Resolution, %d by default" % DEFAULT_RESOLUTION
    )
    parser.add_argument(
        '--tmax',
        metavar='NUM',
        type=float,
        default=DEFAULT_TMAX,
        help="Tmax, %f by default" % DEFAULT_TMAX
    )
    parser.add_argument(
        '--dt',
        metavar='NUM',
        type=float,
        default=DEFAULT_DT,
        help="Step, %f by default" % DEFAULT_DT
    )
    args = parser.parse_args()

    #print 'Printam '
    #print args.resolution

    simulate_pendulum(args.resolution, args.data_file, args.tmax, args.dt)

if __name__ == "__main__":
    main()


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

def compute_r_squared(data, predictions):
    '''
    In exercise 5, we calculated the R^2 value for you. But why don't you try and
    and calculate the R^2 value yourself.

    Given a list of original data points, and also a list of predicted data points,
    write a function that will compute and return the coefficient of determination (R^2)
    for this data.  numpy.mean() and numpy.sum() might both be useful here, but
    not necessary.

    Documentation about numpy.mean() and numpy.sum() below:
    http://docs.scipy.org/doc/numpy/reference/generated/numpy.mean.html
    http://docs.scipy.org/doc/numpy/reference/generated/numpy.sum.html
    '''

    mean = data.mean()
    numerator = np.sum((data - predictions)**2)
    denom = np.sum((data-mean)**2)
    r_squared = 1 - numerator/denom

    return r_squared


import numpy as np
from scipy import special
from scipy import stats as ss

EPS = 1e-8

def generate_truncnorm_multi(ab, mu, sd):
    """
    Use inverse-cdf method.
    Note:
    - difficult to generate x for which mu is many sd away (same sign) from [a, b]
    - in this case, around 5 sd, cdf_ab = (0, 0) or (1, 1)
    - best solution: avoid such inputs
    :param ab: n, 2 | [i] = [a_i, b_i], and a_i < b_i, finite
    :param mu: n,
    :param sd: n,
    :return:
        x: n, | [i] = sample from truncated normal(mu_i, sd_i, ab_i)
    """
    p = np.random.rand(mu.size)
    cdf_ab = ss.norm.cdf(ab, mu[:, np.newaxis], sd[:, np.newaxis])
    z = cdf_ab[:, 0] + p * (cdf_ab[:, 1] - cdf_ab[:, 0])
    z[1-EPS < z] = 1-EPS
    z[z < EPS] = EPS
    x = mu + sd * np.sqrt(2) * special.erfinv(2 * z - 1)
    return x

def logpdf_truncnorm_multi(x, ab, mu, sd):
    """

    :param x: n,
    :param ab: n, 2 | [i] = [a_i, b_i], and a_i < b_i, finite
    :param mu: n,
    :param sd: n,
    :return:
    """
    cdf_ab = ss.norm.cdf(ab, mu[:, np.newaxis], sd[:, np.newaxis])
    delta = cdf_ab[:, 1] - cdf_ab[:, 0]
    delta[delta < EPS] = EPS
    return ss.norm.logpdf(x, mu, sd) - np.log(delta)

def generate_truncnorm(ab, mu, sd, n_samples):
    """
    Use inverse-cdf method in which inv-cdf of truncated normal can be written
    in terms of the normal's cdf and inv-cdf.
    see: https://people.sc.fsu.edu/~jburkardt/presentations/truncated_normal.pdf
    :param ab: 2, | [a, b], and a < b, finite
    :param mu: scalar
    :param sd: scalar
    :param n_samples:
    :return:
        x: n_samples,
    """
    p = np.random.rand(n_samples)
    cdf_ab = ss.norm.cdf(ab, mu, sd)
    z = cdf_ab[0] + p * (cdf_ab[1] - cdf_ab[0])
    # x = ss.norm.ppf(z, mu, sd)  # t = 0.000403
    x = mu + sd * np.sqrt(2) * special.erfinv(2 * z - 1)  # t = 0.00018
    return x

if __name__ == '__main__':
    from timeit import timeit

    # print(generate_truncnorm([0, 2], 1.5, .5, 10))
    ab = np.array([[0, 1], [1, 2], [2, 3]])
    mu = np.array([0, 0, 0])
    sd = np.array([1, 1, 1])
    x = generate_truncnorm_multi(ab, mu, sd)
    nll = -logpdf_truncnorm_multi(x, ab, mu, sd)
    print(x)
    print(nll)
    print()

    args = ([0, 2], 1, .5, 1000)
    n_tries = 2
    print(timeit('f(*args)', number=n_tries, globals=dict(f=generate_truncnorm, args=args))/n_tries)


import numpy as np
import pandas as pd
import matplotlib
from matplotlib import pyplot as plt
import matplotlib.patches as mpatches
from sklearn.decomposition import PCA
from sklearn.cross_validation import cross_val_score as cv_score
from sklearn import datasets
from scipy.stats import pearsonr
from sklearn.datasets import fetch_olivetti_faces
from sklearn.decomposition import RandomizedPCA

def plot_scores(d_scores):
    n_components = np.arange(1,d_scores.size+1)
    plt.plot(n_components, d_scores, 'b', label='PCA scores')
    plt.xlim(n_components[0], n_components[-1])
    plt.xlabel('n components')
    plt.ylabel('cv scores')
    plt.legend(loc='lower right')
    plt.show()

def write_answer_1(optimal_d):
    with open("pca_answer1.txt", "w") as fout:
        fout.write(str(optimal_d))

def plot_variances(d_variances):
    n_components = np.arange(1,d_variances.size+1)
    plt.plot(n_components, d_variances, 'b', label='Component variances')
    plt.xlim(n_components[0], n_components[-1])
    plt.xlabel('n components')
    plt.ylabel('variance')
    plt.legend(loc='upper right')
    plt.show()

def write_answer_2(optimal_d):
    with open("pca_answer2.txt", "w") as fout:
        fout.write(str(optimal_d))

def plot_iris(transformed_data, target, target_names):
    plt.figure()
    for c, i, target_name in zip("rgb", [0, 1, 2], target_names):
        plt.scatter(transformed_data[target == i, 0],
                    transformed_data[target == i, 1], c=c, label=target_name)
    plt.legend()
    plt.show()

def write_answer_3(list_pc1, list_pc2):
    with open("pca_answer3.txt", "w") as fout:
        fout.write(" ".join([str(num) for num in list_pc1]))
        fout.write(" ")
        fout.write(" ".join([str(num) for num in list_pc2]))

def write_answer_4(list_pc):
    with open("pca_answer4.txt", "w") as fout:
        fout.write(" ".join([str(num) for num in list_pc]))

def task1():
	data = pd.read_csv('data_task1.csv')
	print data.shape[1]

	d_scores = []
	for d in xrange(1, data.shape[1] + 1):
		model = PCA(n_components=d)
		model.fit(data)
		scores = cv_score(model, data)
		cur_score = scores.mean()
		d_scores.append(cur_score)

	res = np.argmax(d_scores) + 1
	write_answer_1(res)
	print res
	plot_scores(np.array(d_scores))

def task2():
	data = pd.read_csv('data_task2.csv')
	print data.shape
 	D = data.shape[1]
	model = PCA(n_components=D)
	model.fit(data)
	data_new = model.transform(data)
	d_variances = data_new.var(axis=0)
	#d_variances = sorted(d_variances, reverse=True)
	diffs = [d_variances[i] - d_variances[i+1] for i in xrange(len(d_variances) - 1)]
	res = np.argmax(diffs) + 1
	plot_variances(d_variances)
	print res
	write_answer_2(res)

def task3():
	iris = datasets.load_iris()
	data = iris.data
	target = iris.target
	target_names = iris.target_names
	feature_names = iris.feature_names
	model = PCA(n_components=data.shape[1])
	model.fit(data, target)
	data_new = model.transform(data)
	plot_iris(data_new, target, target_names)
	corrs1 = []
	corrs2 = []
	x1_new = data_new[:, 0] - data_new[:, 0].mean()
	x2_new = data_new[:, 1] - data_new[:, 1].mean()
	for i in xrange(data.shape[1]):
		x_i = data[:, i] - data[:, i].mean()
		corrs1.append(np.abs(pearsonr(x_i, x1_new)[0]))
		corrs2.append(np.abs(pearsonr(x_i, x2_new)[0]))

	list_pc1 = []
	list_pc2 = []
	for i in xrange(len(corrs1)):
		if corrs1[i] > corrs2[i]:
			list_pc1.append(i+1)
		else:
			list_pc2.append(i+1)
	write_answer_3(list_pc1, list_pc2)

def cos(x, y, xk, yk):
	s = 0
	for i in xrange(len(x)):
		s += np.power((x[i] - y[i]), 2)
	return np.power((xk - yk), 2) / s

def task4():
	data = fetch_olivetti_faces(shuffle=True, random_state=0).data
	image_shape = (64, 64)
	model = RandomizedPCA(n_components=10)
	model.fit(data)
	data_new = model.transform(data)
	mean_components = [data_new[:, i].mean() for i in xrange(data_new.shape[1])]
	influence = np.zeros((data_new.shape[0], data_new.shape[1]))
	for i in xrange(data_new.shape[0]):
		for j in xrange(data_new.shape[1]):
			influence[i, j] = cos(data_new[i, :], mean_components, np.abs(data_new[i, j]), mean_components[j])
	res = []
	for i in xrange(influence.shape[1]):
		res.append(np.argmax(influence[:, i]))
	print res
	write_answer_4(res)
	# for i in res:
	# 	plt.imshow(data[i, :].reshape(image_shape))
	# 	plt.show()

task4()


'''
Created on May 4, 2016

@author: Edielson
'''
import numpy as np

DEFAULT_MAX_ITERATIONS = 4

class Scaling(object):
    '''
    classdocs
    '''

    def __init__(self, max_iterations = None):
        '''
        Constructor
        '''

        # Define the maximum number of iterations.
        # If not specified by the user, use the default number of iterations.
        if max_iterations == None:
            self.__max_it = DEFAULT_MAX_ITERATIONS
        else:
            self.__max_it = max_iterations

    def GeometricMean(self,A):
        '''
        Constructor
        '''

        #number of rows in the matrix X
        m = len(A)
        n = len(A.transpose())

        r = np.zeros(m)
        s = np.zeros(n)

        t=0
        X = A

        while t < self.__max_it:
            print('iteration: %s'%(t+1))
            for i in xrange(m):
                #get the maximum value at row i
                max_x = np.asscalar(np.max(X[i,:], 1))
                #get the minimum value at row i
                min_x = np.asscalar(np.min(X[i,:], 1))
                #calculate the geometric mean
                r[i]=np.nan_to_num(1.0*np.sqrt(1.0/(max_x*min_x)))

            #mount the respective diagonal matrix for r
            R = np.diag(r)
            #scale matrix X based on R
            X=R*X

            for j in xrange(n):
                #get the maximum value at column j
                max_x = np.asscalar(np.max(X[:,j], 0))
                #get the minimum value at column j
                min_x = np.asscalar(np.min(X[:,j], 0))
                #calculate the geometric mean
                s[j]=np.nan_to_num(1.0*np.sqrt(1.0/(max_x*min_x)))

            #mount the respective diagonal matrix for s
            S = np.diag(s)
            #scale matrix X based on S
            X=X*S
            t=t+1

        return X

    def ArithmeticMean(self,A):

        #number of rows in the matrix X
        m = len(A)
        n = len(A.transpose())

        r = np.zeros(m)
        s = np.zeros(n)

        t=0
        X = A

        while t < self.__max_it:
            print('iteration: %s'%(t+1))
            for i in xrange(m):
                #get the sum of the values at row i
                sum_x = np.asscalar(np.sum(X[i,:], 1))
                #calculate the arithmetic mean
                r[i]=np.nan_to_num(1.0*n/sum_x)

            #mount the respective diagonal matrix for r
            R = np.diag(r)
            #scale matrix X based on R
            X=R*X

            for j in xrange(n):
                #get the sum of the values at column j
                sum_x = np.asscalar(np.sum(X[:,j], 0))
                #calculate the arithmetic mean
                s[j]=np.nan_to_num(1.0*m/sum_x)

            #mount the respective diagonal matrix  s
            S = np.diag(s)
            #scale matrix X based on S
            X=X*S
            t=t+1

        return X

    def Equilibration(self,X):

        #number of rows in the matrix X
        m = len(X)
        n = len(X.transpose())

        for i in xrange(m):
            #get the maximum value at row i
            max_x = np.asscalar(np.max(X[i,:], 1))
            X[i,:]=[X[i,j]/max_x for j in range(n)]

        for j in xrange(n):
            #get the maximum value at column j
            max_x = np.asscalar(np.max(X[:,j], 0))
            X[:,j]=np.matrix([X[i,j]/max_x for i in range(m)]).transpose()

        return X


# -*- coding: utf-8 -*-
""" Variation of Information

Variation of Information (*VI*) [Meilla2007]_ is an information theoretic criterion
for comparing two partitions. It is based on the classic notions of entropy and mutual information.
In a nutshell, VI measures the amount of information that is lost or gained in changing from
clustering :math:`A` to clustering :math:`B`. VI is a true metric, is always non-negative and symmetric.
The following formula is used to compute the VI between two groups:

.. math::
    VI(A, B) = [H(A) - I(A, B)] + [H(B) - I(A, B)]

Where :math:`H` denotes the entropy computed for each partition separately,
and :math:`I` the mutual information between clusterings :math:`A` and :math:`B`.

The resulting distance score can be adjusted to bound it between :math:`[0, 1]` as follows:

.. math::
    VI^{*}(A,B) = \\frac{1}{\\log{n}}VI(A, B)

|

-----

.. [Meilla2007] Meilă, M. (2007). Comparing clusterings—an information based distance. Journal of multivariate analysis, 98(5), 873-895.
.. [Dimitriadis2009] Dimitriadis, S. I., Laskaris, N. A., Del Rio-Portilla, Y., & Koudounis, G. C. (2009). Characterizing dynamic functional connectivity across sleep stages from EEG. Brain topography, 22(2), 119-133.
.. [Dimitriadis2012] Dimitriadis, S. I., Laskaris, N. A., Michael Vourkas, V. T., & Micheloyannis, S. (2012). An EEG study of brain connectivity dynamics at the resting state. Nonlinear Dynamics-Psychology and Life Sciences, 16(1), 5.
"""
# Author: Avraam Marimpis <avraam.marimpis@gmail.com>
# Author: Stavros Dimitriadis <stdimitr@gmail.com>

import numpy as np

from dyconnmap.ts.entropy import entropy

def variation_information(indices_a: np.ndarray, indices_b: np.ndarray) -> float:
    """ Variation of Information

    Parameters
    ----------
    indices_a : array-like, shape(n_samples)
        Symbolic time series.

    indices_b : array-like, shape(n_samples)
        Symbolic time series.

    Returns
    -------
    vi : float
        Variation of information.
    """
    n1 = len(indices_a)
    n2 = len(indices_b)

    if n1 != n2:
        pass

    entropy1 = entropy(indices_a)
    entropy2 = entropy(indices_b)

    MI, _ = __mi(indices_a, -entropy1, indices_b, -entropy2)

    entropy1 = -entropy1
    entropy2 = -entropy2
    VI_value = entropy1 + entropy2 - 2 * MI

    NVI = VI_value / np.log(n1)

    return VI_value, NVI

def __unique_symbols(indices):
    """

    """
    N = len(indices)
    unique, counts = np.unique(indices, return_counts=True)
    len_counts = len(counts)
    U = np.zeros((len_counts, N))
    indices = indices.flatten()
    for i in range(len_counts):
        tmp = np.where(indices == unique[i])
        U[i, tmp[0]] = 1

    return U

def __mi(indices_a, entropy_a, indices_b, entropy_b):
    """

    """
    N = len(indices_a)

    Ua = __unique_symbols(indices_a)
    Ub = __unique_symbols(indices_b)

    Sab = Ua.dot(Ub.T) / np.float32(N)
    Sa = np.diag(Ua.dot(Ua.T) / np.float32(N))
    Sb = np.diag(Ub.dot(Ub.T) / np.float32(N))

    # Add dummy dimension (needed for following computations).
    Sa = np.expand_dims(Sa, axis=1)
    Sb = np.expand_dims(Sb, axis=1)

    SS = Sab * np.log10(Sab / (Sa * Sb.T))

    MI = np.nansum(np.nansum(SS))
    NMI = 2 * MI / (entropy_a + entropy_b)

    return MI, NMI


import numpy as np

def ll2xy(lat, lon, sgn=-1, central_meridian=0, standard_parallel=71):
    '''
    LL2XY - converts lat lon to polar stereographic

   Converts from geodetic latitude and longitude to Polar
   Stereographic (X, Y) coordinates for the polar regions.
   Author: Michael P. Schodlok, December 2003 (map2ll)

   Usage:
      x, y = ll2xy(lat, lon, sgn)
      x, y = ll2xy(lat, lon, sgn, central_meridian, standard_parallel)

 - sgn = Sign of latitude	1 : north latitude (default is mer = 45 lat = 70)
 						   -1 : south latitude (default is mer = 0  lat = 71)
    '''

    assert sgn == 1 or sgn == -1, 'error: sgn should be either 1 or -1'

    #Get central_meridian and standard_parallel depending on hemisphere
    if sgn == 1:
        delta = 45
        slat = 70
        print('        ll2xy: creating coordinates in north polar stereographic (Std Latitude: 70N Meridian: 45)')
    else:
        delta = central_meridian
        slat = standard_parallel
        print('        ll2xy: creating coordinates in south polar stereographic (Std Latitude: 71S Meridian: 0)')

    # Conversion constant from degrees to radians
    #cde = 57.29577951
    # Radius of the earth in meters
    re = 6378.273 * 10**3
    # Eccentricity of the Hughes ellipsoid squared
    ex2 = .006693883
    # Eccentricity of the Hughes ellipsoid
    ex = np.sqrt(ex2)

    latitude = np.abs(lat) * np.pi / 180.
    longitude = (lon + delta) * np.pi / 180.

    # compute X and Y in grid coordinates.
    T = np.tan(np.pi / 4 - latitude / 2) / ((1 - ex * np.sin(latitude)) / (1 + ex * np.sin(latitude)))**(ex / 2)

    if (90 - slat) < 1.e-5:
        rho = 2. * re * T / np.sqrt((1. + ex)**(1. + ex) * (1. - ex)**(1. - ex))
    else:
        sl = slat * np.pi / 180.
        tc = np.tan(np.pi / 4. - sl / 2.) / ((1. - ex * np.sin(sl)) / (1. + ex * np.sin(sl)))**(ex / 2.)
        mc = np.cos(sl) / np.sqrt(1.0 - ex2 * (np.sin(sl)**2))
        rho = re * mc * T / tc

    y = -rho * sgn * np.cos(sgn * longitude)
    x = rho * sgn * np.sin(sgn * longitude)

    cnt1 = np.nonzero(latitude >= np.pi / 2.)[0]

    if cnt1:
        x[cnt1, 0] = 0.0
        y[cnt1, 0] = 0.0
    return x, y


import numpy as np

sum_primes = 2

def check_prime(integer):
    for i in range(3, int(integer**(1/2))+1, 2):
        if integer % i == 0:
            return False
    else:
        return True

for i in range(3, 2*1000000, 2):
    if check_prime(i):
        sum_primes += i

print("Sum of primes under 2 million:", sum_primes)


import numpy as np

X= np.array([
    [0, -6],
    [4,4],
    [0,0],
    [-5,2]])

#Initial points
medoids_initial =np.array([[-5,2], [0,-6]])

##K- Medioids Algorithm
costs = list()
# Step 1
z = np.array([[-5,2], [0,-6]])
zs = list([z])

##K Mediods Algorithm
while True:
  clusters = np.array([np.argmin([np.linalg.norm(X[i] - z[j]) for j in range(len(z))]) for i in range(len(X))])
  clusters = np.array([X[np.where(clusters == label)[0]] for label in set(clusters)])
  z = X[[np.argmin([sum([np.linalg.norm(X[i] - X[j]) for i in range(len(cluster))]) for j in range(len(X))]) for cluster in clusters]]
  zs.append(z)
  cost = sum([sum([np.linalg.norm(clusters[j][i] - z[j]) for i in range(len(clusters[j]))]) for j in range(len(z))])
  print ("Cost:", cost)
  costs.append(cost)
  if len(costs) >= 2 and costs[-1] > costs[-2]:
    break

detailed_clusters= clusters
final_centroids= z

Machine-Learning-with-Python- From-LM-to-DL/Unit 4. Unsupervised Learning/00_k_medioids.py


# %%
#Apllying a filter on a sinusoidal signal with  noise at 8000 Hz and retrieving the pure sinusoidal tone of the sum of sin waves 10 Hz and 20 Hz
from cProfile import label
import numpy as np
from numpy import logspace
import matplotlib.pyplot as plt
from scipy import signal

#define a function for plotting the Frequency response of the filter
def plot_response(fs, w, h, title):
    plt.figure()
    plt.plot(0.5*fs*w/np.pi, 20*np.log10(np.abs(h)))
    plt.ylim(-40, 5)
    #plt.xlim(0, 0.5*fs)
    plt.xscale('log')

    plt.grid(True)
    plt.xlabel('Frequency (Hz)')
    plt.ylabel('Gain (dB)')
    plt.title(title)

#%%
#Generate a signal for filtering
def generate_random_signal():
    t= np.linspace(0, 1, 44000, False) # 1 sec
    f0= 10
    sig = 2* np.sin(2*np.pi*f0*t) + 3* np.sin(2*np.pi*2*f0*t) + 8* np.sin(2*np.pi*800*f0*t)           #np.random.rand(t.shape[0]
    return (t, sig)
t, sig = generate_random_signal()

#%%
# IIR Low-pass Butterworth filter response on the signal
sos = signal.butter(N = 10, Wn = 3250, btype = 'lp', fs = 44000, output = 'sos')
filtered = signal.sosfilt(sos, sig)
fig, (ax1, ax2) = plt.subplots( 2, 1, sharex=True)
ax1.plot(t, sig)
ax1.set_title('10 and 20 Hz sinusoids with 8kHz interferences')
ax1.axis([0, 1, -15, 15])
ax2.plot(t, filtered)
ax2.set_title('After Filtering the 8kHz with IIR Butterworth filter')
ax2.axis([0, 1, -5, 5])
ax2.set_xlabel('Time [seconds]')
plt.tight_layout()
plt.show()
#%%
# Seperate of 10 Hz and 20 Hz signals using IIR Butterworth LP and HP for seperation
sos_lp_2=signal.butter(N = 10, Wn = 15, btype = 'lowpass', fs = 44000, output = 'sos')
sos_hp_2=signal.butter(N = 10, Wn = 15, btype = 'highpass', fs = 44000, output = 'sos')
filtered_lp_2= signal.sosfilt(sos_lp_2, filtered)
filtered_hp_2= signal.sosfilt(sos_hp_2,filtered)
fig, (ax1, ax2) = plt.subplots( 2, 1, sharex=True)
ax1.plot(t, filtered)
ax1.set_title('filtered signal of 10 and 20 Hz sinusoids using IIR Butterworth filter')
ax1.axis([0, 1, -5, 5])
ax2.plot(t, filtered_lp_2, label='10 Hz')
ax2.plot(t,filtered_hp_2, label=('20 Hz'))
ax2.axis([0, 1, -4, 4])
ax2.set_xlabel('Time [seconds]')
plt.tight_layout()
plt.legend(bbox_to_anchor =(0.70, 1.15), ncol = 2 )
plt.show()

#%%
# FIR Low-pass filter
fs = 44000        #sampling freq
cutoff = 3250     #Cutoff freq for gain drop
trans_width = 250 # width of transition from passband to stopband in Hz
numtaps = 200     #Size of the FIR filter

#%%
#Construct a Low-pass FIR filter
taps = signal.remez(numtaps, [0, cutoff, cutoff+trans_width, 0.5*fs], [1,0], Hz= fs)
w, h = signal.freqz(taps, [1], worN=2000)

#%%
#Applying the FIR LP filter to the signal
y = signal.lfilter(taps, 1.0, sig)
fig, (ax1, ax2) = plt.subplots( 2, 1, sharex=True)
ax1.plot(t, sig)
ax1.set_title('10 and 20 Hz sinusoids with 8kHz interferences')
ax1.axis([0, 1, -15, 15])
ax2.plot(t, y)
ax2.set_title('After Filtering the 8kHz with FIR filter (signal.remez)')
ax2.axis([0, 1, -5, 5])
ax2.set_xlabel('Time [seconds]')
plt.tight_layout()
plt.show()

#%%
#Plot the frequency response of the FIR Low-pass (Filter signal.remez)
plot_response(fs, w, h, "FIR Low-pass (Filter signal.remez)")

#%%
#Construct a Low-pass FIR LP filter with Kaiser Window method
nyq_rate = fs/2.0
width = 8/nyq_rate
ripple_dB = 10
N, beta = signal.kaiserord(ripple_dB, width)
cutoff_hz = cutoff

taps_2 = signal.firwin(N, cutoff_hz/nyq_rate, window=('kaiser', beta))
w_2, h_2 = signal.freqz(taps_2, [1], worN=2000)
y_2 = signal.lfilter(taps_2, 1.0, sig)

fig, (ax1, ax2) = plt.subplots( 2, 1, sharex=True)
ax1.plot(t, sig)
ax1.set_title('10 and 20 Hz sinusoids with 8kHz interferences')
ax1.axis([0, 1, -15, 15])
ax2.plot(t, y_2)
ax2.set_title('After Filtering the 8kHz with FIR LP filter(kaiser window signal.firwin)')
ax2.axis([0, 1, -5, 5])
ax2.set_xlabel('Time [seconds]')
plt.tight_layout()
plt.show()

plot_response(fs, w_2, h_2, "FIR Low-pass filter (signal.firwin (kaiser))")

#%%
#Construct a FIR BP filter with kaiser window method
f1, f2= 1/nyq_rate, 15/nyq_rate

taps_2_bandpass_kaiser = signal.firwin(numtaps, [f1, f2], pass_zero=False)
w_2_bp_kaiser,h_2_bp_kaiser = signal.freqz(taps_2_bandpass_kaiser, [1], worN=2000)
y_2_bp_kaiser = signal.lfilter(taps_2_bandpass_kaiser, 1.0, sig)

fig, (ax1, ax2) = plt.subplots(2, 1, sharex=True)
ax1.plot(t, sig)
ax1.set_title('10 and 20 Hz sinusoids with 8kHz interferences')
ax1.axis([0, 1, -15, 15])
ax2.plot(t, y_2_bp_kaiser)
ax2.set_title('After Filtering the 8kHz with FIR BP filter(kaiser window signal.firwin)')
plt.tight_layout()
plt.show()

#Plot the frequency response of BP FIR filter (kaiser window method)
plot_response(fs, w_2_bp_kaiser, h_2_bp_kaiser, "FIR Band-pass filter (signal.firwin (kaiser))")

#%%
#Seperate of 10 Hz and 20 Hz signals using FIR LP and HP for seperation
cutoff_2 = 10
cutoff_2_hp = 44
trans_width_2 = 1
numtaps_2 = 8000

#%%
#Construct a Low-pass FIR filter
taps_2_lp = signal.remez(numtaps_2, [0, cutoff_2, cutoff_2+trans_width_2, 0.5*fs], [1,0], Hz= fs)
w_2_lp, h_2_lp = signal.freqz(taps_2_lp, [1], worN=2000)

#%%
#Construct a High-pass FIR filter
taps_2_hp = signal.remez(numtaps_2, [0, cutoff_2_hp-trans_width_2, cutoff_2_hp, 0.5*fs], [0,1], Hz= fs)
w_2_hp, h_2_hp = signal.freqz(taps_2_hp, [1], worN=2000)

#%%
#Apply the FIR HP and LP filters
y_2_lp = signal.lfilter(taps_2_lp, 1.0, y)
y_2_hp = signal.lfilter(taps_2_hp, 1.0, y)

#%%
#Plot the 2 signals seperate
fig, (ax1, ax2)= plt.subplots(2, 1, sharex=True)
ax1.plot(t, y_2_hp)
ax1.set_title('20 Hz sine wave')
ax1.axis([0, 1, -6, 6])
ax2.plot (t, y_2_lp)
ax2.set_title('10 Hz sine wave')
ax2.axis([0, 1, -6, 6])
plt.tight_layout()
plt.show()

#%%
"""
#Construct a Bandpass filter to seperate 10 and 20 Hz
#Band pass filter from 1 to 16 Hz
band = [2,12]
numtaps_bandpass = 1000
edges = [0, band[0] - trans_width_2, band[0], band[1], band[1] + trans_width_2, 0.5*fs]
taps_bandpass_10_Hz = signal.remez(numtaps_bandpass, edges, [0, 1, 0], Hz=fs)
w_bp_10_Hz, h_bp_10_Hz = signal.freqz(taps_bandpass_10_Hz, [1], worN=2000)

band_pass_for_10_Hz = signal.lfilter(taps_bandpass_10_Hz, 1.0, y)

#Band pass filter from 16 to 100 Hz
band_2 = [15, 50]
edges_2 = [0, band_2[0] - trans_width_2, band_2[0], band_2[1], band_2[1] + trans_width_2, 0.5*fs]
taps_bandpass_20_Hz = signal.remez(numtaps_bandpass, edges_2, [0, 1, 0], Hz=fs)
w_bp_20_Hz, h_bp_20_Hz = signal.freqz(taps_bandpass_20_Hz, [1], worN=2000)
band_pass_for_20_Hz = signal.lfilter(taps_bandpass_20_Hz, 1.0, y)

#Plot the 2 signals seperate
fig, (ax1, ax2)= plt.subplots(2, 1, sharex=True)
ax1.plot(t, band_pass_for_20_Hz)
ax1.set_title('20 Hz sine wave')
ax1.axis([0, 1, -6, 6])
ax2.plot (t, band_pass_for_10_Hz)
ax2.set_title('10 Hz sine wave')
ax2.axis([0, 1, -6, 6])
plt.tight_layout()
plt.show()

"""

#%%
#Plot the Frequency response of the filter

plot_response(fs, w_2_hp, h_2_hp, "FIR High-pass Filter")
plot_response(fs, w_2_lp, h_2_lp, "FIR Low-pass Filter")
#plot_response(fs, w_bp_10_Hz, h_bp_10_Hz, "FIR Band-pass Filter 10 Hz")
#plot_response(fs, w_bp_20_Hz, h_bp_20_Hz, "FIR Band-pass Filter 20 Hz")

# %%
# Power Spectrum / signal.welch
fs = 44000
f, Pxx_spec = signal.welch(sig, fs, window ='flattop', nperseg = 1024, scaling = 'spectrum')
plt.figure()
plt.semilogy(f, np.sqrt(Pxx_spec))
plt.xlim(0, 10000)

plt.xlabel('Frequency [Hz]')
plt.ylabel('Linear spectrum [V RMS]')
plt.title('Power spectrum before filter is applied')
plt.show()

# %%
#IIR Butterworth filtered signal Power Spectrum
fs = 44000
f, Pxx_spec = signal.welch(filtered, fs, window ='flattop', nperseg = 1024, scaling= 'spectrum')
plt.figure()
plt.semilogy(f, np.sqrt(Pxx_spec))
plt.xlim(0,10000)
plt.xlabel ('Frequency [Hz]')
plt.ylabel ('Linear Spectrum [V RMS]')
plt.title (' IIR Butterworth LP filtered signal Power Spectrum')
plt.show ()

# %%
#FIR filtered signal Power Spectrum
fs = 44000
f, Pxx_spec = signal.welch(y, fs, window ='flattop', nperseg = 1024, scaling= 'spectrum')
plt.figure()
plt.semilogy(f, np.sqrt(Pxx_spec))
plt.xlim(0,10000)
plt.xlabel ('Frequency [Hz]')
plt.ylabel ('Linear Spectrum [V RMS]')
plt.title (' FIR LP filtered signal Power Spectrum')
plt.show ()

#%%

# simulation of the system response to the butterworth filter used to eliminate noise
from scipy.signal import lsim
b, a = signal.butter(N=20, Wn=2*np.pi*3250, btype='lowpass',fs=44000, analog=False)
tout, yout, xout = lsim((b, a), U=sig, T=t)
plt.plot (t, sig, 'r', alpha=0.5, linewidth=1, label='input')
plt.plot (tout, yout, 'k', alpha = 1, linewidth=1, label='output')
plt.legend (loc='best', shadow=False, framealpha=1)
plt.grid (alpha=0.5)
plt.xlabel ('time')
plt.show ()

# %%
# Fast Fourier Transformation of input and output signals
f0=10
N = int(10*(fs/f0))

yf_input = np.fft.rfft(sig)
y_input_mag_plot = np.abs(yf_input)/N

f= np.linspace (0, (N-1)*(fs/N),N )

f_plot = f[0:int(N/2+1)]
y_input_mag_plot = 2*y_input_mag_plot[0:int(N/2+1)]
y_input_mag_plot[0] = y_input_mag_plot[0] / 2

fig, (ax1, ax2) = plt.subplots(2,1, sharex=True)
fig.suptitle('IIR butterworth Low-pass Filter')
ax1.plot(f_plot, y_input_mag_plot)
ax1.grid(alpha=0.3)

ax1.set_ylabel('Amplitute [dB]')

yf_output = np.fft.rfft(filtered)
y_output_mag_plot = np.abs(yf_output)/N
y_output_mag_plot = 2* y_output_mag_plot[0:int(N/2+1)]
y_output_mag_plot[0]= y_output_mag_plot[0]/2
ax2.plot(f_plot, y_output_mag_plot)

plt.plot(f_plot, y_output_mag_plot, label='output signal')
plt.grid(alpha=0.3)
plt.xlabel('Frequency [Hz]')
plt.ylabel('Amplitute [dB]')
plt.xscale('log')
plt.legend()

plt.show()

#%%
#Plot the signal in frequency domain after using FIR LP (signal.remez)
fig, (ax1, ax2) = plt.subplots(2,1, sharex=True)
fig.suptitle('FIR Low-pass Filter (signal.remez)')
ax1.plot(f_plot, y_input_mag_plot, label= 'input signal')
ax1.grid(alpha=0.3)

ax1.set_ylabel('Amplitute [dB]')

yf_output = np.fft.rfft(y)
y_output_mag_plot = np.abs(yf_output)/N
y_output_mag_plot = 2* y_output_mag_plot[0:int(N/2+1)]
y_output_mag_plot[0]= y_output_mag_plot[0]/2
ax2.plot(f_plot, y_output_mag_plot)

plt.plot(f_plot, y_output_mag_plot, label= 'output signal')
plt.grid(alpha=0.3)
plt.xlabel('Frequency [Hz]')
plt.ylabel('Amplitute [dB]')
plt.xscale('log')
plt.legend()

plt.show()

#%%
#Plot the signal in frequency domain after using FIR LP kaiser window method
fig, (ax1, ax2) = plt.subplots(2,1, sharex=True)
fig.suptitle('FIR Low-pass Kaiser Window method')
ax1.plot(f_plot, y_input_mag_plot, label='input signal')
ax1.grid(alpha=0.3)

ax1.set_ylabel('Amplitute [dB]')

yf_output = np.fft.rfft(y_2)
y_output_mag_plot = np.abs(yf_output)/N
y_output_mag_plot = 2* y_output_mag_plot[0:int(N/2+1)]
y_output_mag_plot[0]= y_output_mag_plot[0]/2
ax2.plot(f_plot, y_output_mag_plot)

plt.plot(f_plot, y_output_mag_plot, label= 'output signal')
plt.grid(alpha=0.3)
plt.xlabel('Frequency [Hz]')
plt.ylabel('Amplitute [dB]')
plt.xscale('log')
plt.legend()

plt.show()

# %%
#Bode plot for input and output
# needs more work for proper implementation
H= yf_output/ yf_input
Y = np.imag (H)
X = np.real (H)
#Mag_of_H = 20*cmath.log10(Y)
f = logspace(-1,0.001) # frequencies from 0 to 10**5
sys = signal.lti([H],f)
w, mag, phase = signal.bode(sys, n= f)
#print (w, mag, phase)
plt.plot(f, w, label= 'Frequency rad/sec')
plt.plot(f, mag, label= 'Magnitude [dB]' )
plt.plot(f, phase, label='Phase array [deg]' )
plt.grid(which='both', axis= 'both')
plt.legend()
#plt.xlabel('Real numbers R')
#plt.ylabel('Imaginary numbers I')
#plt.scatter(X,Y)

#plt.show()

#fig= plt.figure()
#ax = fig.add_subplot(projection = 'polar')
#c= ax.scatter(X,Y)
#plt.title('Polar representation of ')


""""
README
======
This file contains Python codes.
======
"""

""" Solve Ax=B with the Jacobi method """
import numpy as np

def jacobi(A, B, n, tol=1e-10):
    # Initializes x with zeroes with same shape and type as B
    x = np.zeros_like(B)

    for it_count in range(n):
        x_new = np.zeros_like(x)
        for i in range(A.shape[0]):
            s1 = np.dot(A[i, :i], x[:i])
            s2 = np.dot(A[i, i + 1:], x[i + 1:])
            x_new[i] = (B[i] - s1 - s2) / A[i, i]

        if np.allclose(x, x_new, tol):
            break

        x = x_new

    return x

A = np.array([[10., -1., 2., 0.],
              [-1., 11., -1., 3.],
              [2., -1., 10., -1.],
              [0.0, 3., -1., 8.]])
B = np.array([6., 25., -11., 15.])
n = 25

x = jacobi(A,B,n)
print "x =", x


#!/usr/bin/env python3

import numpy as np
from scipy import linalg as slinalg
from numpy import random
import math
import matx_common
from typing import Dict, List

class cholesky:
    def __init__(self, dtype: str, size: List[int]):
        self.size = size
        self.dtype = dtype
        np.random.seed(1234)

    def run(self):
        n = self.size[0]

        # Create a positive-definite matrix
        A = np.random.randn(n, n)
        B = np.matmul(A, A.conj().T)
        B = B + n*np.eye(n)

        L = np.linalg.cholesky(B)

        return {
            'B': B,
            'L': L
        }

class lu:
    def __init__(self, dtype: str, size: List[int]):
        self.size = size
        self.dtype = dtype
        np.random.seed(1234)

    def run(self):
        m, n = self.size[0], self.size[1]

        A = np.random.randn(m, n)
        P, L, U = slinalg.lu(A)

        return {
            'A': A,
            'P': P,
            'L': L,
            'U': U,
        }

class qr:
    def __init__(self, dtype: str, size: List[int]):
        self.size = size
        self.dtype = dtype
        np.random.seed(1234)

    def run(self):
        m, n = self.size[0], self.size[1]

        A = np.random.randn(m, n)
        Q, R = np.linalg.qr(A)

        return {
            'A': A,
            'Q': Q,
            'R': R,
        }

class svd:
    def __init__(self, dtype: str, size: List[int]):
        self.size = size
        self.dtype = dtype
        np.random.seed(1234)

    def run(self):
        m, n = self.size[0], self.size[1]

        A = np.random.randn(m, n)
        U, S, V = np.linalg.svd(A)

        return {
            'A': A,
            'U': U,
            'S': S,
            'V': V
        }

class eig:
    def __init__(self, dtype: str, size: List[int]):
        self.size = size
        self.dtype = dtype
        np.random.seed(1234)

    def run(self):
        n = self.size[0]
        # Create a positive-definite matrix
        A = np.random.randn(n, n)
        B = np.matmul(A, A.conj().T)
        B = B + n*np.eye(n)

        W, V = np.linalg.eig(B)
        return {
            'B': B,
            'W': W,
            'V': V
        }

class det:
    def __init__(self, dtype: str, size: List[int]):
        self.size = size
        self.dtype = dtype
        np.random.seed(1234)

    def run(self):
        n = self.size[0]

        # Create a positive-definite matrix
        A = np.random.randn(n, n)
        det = np.linalg.det(A)

        return {
            'A': A,
            'det': det
        }


"""
Coded By: Puneet Dheer
Date:2-Jan-2019
"""

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

def variance(X):

    X_var = np.sum(np.square(X - np.mean(X) ))

    return X_var

def covariance(X, Y):

    X_var = (X - np.mean(X))
    Y_var = (Y - np.mean(Y))
    cov = np.sum(X_var * Y_var)

    return cov

def coeffs(X, Y):

    slope = covariance(X, Y) / variance(X)
    intercept = np.mean(Y) - (slope * np.mean(X))

    return slope, intercept

def simple_linear_regression(X, Y):

    slope,intercept = coeffs(X, Y)
    coeff = np.array([intercept, slope])
    predicted = (slope * X) + intercept

    return coeff, predicted

def mse_metric(actual, predicted):

    # Mean square error
    error = actual - predicted
    mse = np.mean(np.square(error), axis = 0) # assuming the mean of error is zero ~N(0,var)

    return mse

def mae_metric(actual, predicted):

    # Mean absolute error
    error = np.abs(actual - predicted)
    mae = np.mean(error, axis = 0)

    return mae

def goodness_of_fit(actual, predicted):

    explained_variance = np.sum(np.square(predicted - np.mean(actual) )) # sum of squared regression
    unexplained_variance = np.sum(np.square(actual - predicted)) # sum of squared error
    total_variance = explained_variance + unexplained_variance
    gf = 1-(unexplained_variance / total_variance)

    return gf

if __name__ == "__main__":

    dataset = pd.read_csv('Sample_Data_SLR.csv', header = 0) # dataset column wise

    X = dataset.iloc[:, :-1].values # independent variable
    Y = dataset.iloc[:, 1].values # dependent variable

    if (Y.shape==(len(Y), 1)):
        pass
    else:
        Y = Y.reshape(len(Y), 1)

    coefficients, predicted = simple_linear_regression(X, Y)

    print "MS Error: \n", mse_metric(Y, predicted)
    print "RMS Error: \n", np.sqrt(mse_metric(Y, predicted))
    print "MA Error: \n", mae_metric(Y, predicted)
    print "Goodness-of-fit: \n", goodness_of_fit(Y, predicted)
    print "Coefficients: " , coefficients

    plt.figure()
    plt.scatter(X, Y, color = 'red')
    plt.plot(X, predicted, color = 'blue')
    plt.title('Simple Linear Regression')
    plt.xlabel('Exogenous Variable [aka. Independent or Predictor]')
    plt.ylabel('Endogenous Variable [aka. Dependent or Response]')
    plt.tight_layout()
    plt.show()


# np_baseball is available

# Import numpy
import numpy as np

b = np.array([[74., 72., 72., 73., 69., 69., 71., 76., 150.], [74., 72., 72., 73., 69., 69., 71., 76., 71.]])
np_baseball = b.transpose()

# Create np_height from np_baseball
np_height = np_baseball[:,0]

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

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


"""
In the previous examples, we solved a constrained Rosenbrock problem and the sphere problem.

While both of these problems are nonlinear, they're really just a mix of simple polynomials. This means that we can
express it with overloaded Python operators: [+, -, *, /, **, ...] and so on.

But what if we want to use a function that's not part of simple arithmetic - something like cos(x), for example?
That's what we'll explore here!

-----

One of the coolest things about the `Opti` stack is that it's fast - really, **really** fast. You can solve
nonlinear, nonconvex optimization problems with thousands of variables in mere seconds on a laptop, thanks to
automatic differentiation (AD) provided by CasADi and modern optimization methods via IPOPT.

In order for AD to work, we need to be able to make a list (more precisely, a directed graph) of each mathematical
operation (think +, -, *, /, **, log(), fabs(), etc.) that's applied throughout our optimization formulation (some
call this list a "trace" in the literature). This means we can't just use NumPy out of the box like we'd like to,
because some of its functions break our trace.

Instead, we need to use a custom math library, which sounds scary at first. However, the AeroSandbox development team
has tried to make this as seamless to you as possible - by writing our own NumPy with identical syntax! Here's how
this works:

	* `aerosandbox.numpy` imports the entirety of NumPy.

	* For NumPy functions that break our AD trace (e.g. `np.sum()`), we've rewritten our own versions of them. This
	means:

		* If you pass normal NumPy arrays to these functions, they'll work 100% exactly the same as they would in
		original NumPy - same result and same speed.

		* If you pass optimization variables to these functions, they'll intelligently switch over to a version of the
		function that allows us to preserve the AD trace.

	* **So what does this mean for you, dear user?** It means that when working with AeroSandbox, all you need to do
	is replace `import numpy as np` with `import aerosandbox.numpy as np`, and you're good to go!

	* Caveat: Not all NumPy functions that should be overwritten have been overwritten - we've done our best,
	but there are *sooo* many obscure NumPy functions! If you get an error on a function you want to use,
	raise an issue ticket!

You'll notice that in our last example, we imported `aerosandbox.numpy` in order to use the `sum()` function.

Here, let's do an example with some other functions.
"""
import aerosandbox as asb
import aerosandbox.numpy as np

opti = asb.Opti()

x = opti.variable(init_guess=3)

f = np.exp(  # You can use normal operations from NumPy like this!
    np.cos(  # These functions are intelligently overloading in the background...
        x
    )
)

opti.minimize(f)

opti.subject_to([
    x >= 0,
    x <= np.pi / 2
])
"""
Note another feature we just introduced here: you can give `opti.subject_to()` a list of constraints, not just a
single constraint like we did before! Often, this makes for cleaner, more readable code.

Also, note that you can declare variables, constraints, and objectives in any order. As long as they're all set in
place by the time you call `sol = opti.solve()`, you're good. Speaking of, let's solve!
"""
sol = opti.solve()

x_opt = sol.value(x)

print(f"x = {x_opt}")
"""

Nice, it solved! The value of x at the optimum turns out to be equal to pi / 2.

Note that there are tons and tons of nonlinear functions you can use - everything from logarithms to vector norms to
linear solves to eigenvalue decompositions. The list is quite extensive and can be viewed at:
`aerosandbox/numpy/test_numpy/test_all_operations_run.py`, where many of the valid operations are listed.

This would not be possible without tons of hard work by the CasADi team!

"""

tutorial/1 - Optimization and Math/4 - (More) Nonlinear functions.py


# --------------
# Importing header files
import numpy as np
import warnings

warnings.filterwarnings('ignore')

#New record
new_record=[[50,  9,  4,  1,  0,  0, 40,  0]]

#Reading file
data = np.genfromtxt(path, delimiter=",", skip_header=1)

#Code starts here
census = np.concatenate((new_record, data),axis=0)

age = census[:,0]
max_age = np.max(age)
print(max_age)
min_age = np.min(age)
print(min_age)
age_mean = round(np.mean(age),2)
print(age_mean)
age_std = round(np.std(age))
print(age_std)

#Step3
race_0 = census[census[:,2]==0]
race_1 = census[census[:,2]==1]
race_2 = census[census[:,2]==2]
race_3 = census[census[:,2]==3]
race_4 = census[census[:,2]==4]

len_0 = len(race_0)
len_1 = len(race_1)
len_2 = len(race_2)
len_3 = len(race_3)
len_4 = len(race_4)

minority_race = min(len_0,len_1,len_2,len_3,len_4)
print(minority_race)

#Step4
senior_citizens = census[census[:,0]>60]
working_hours_sum = senior_citizens.sum(axis=0)[6]
senior_citizens_len = len(senior_citizens)
avg_working_hours = round(working_hours_sum/senior_citizens_len,2)
print(avg_working_hours)

#Step5
high = census[census[:,1]>10]
low = census[census[:,1]<=10]
avg_pay_high = round(np.mean(high[:,7]),2)
avg_pay_low = round(np.mean(low[:,7]),2)
print(avg_pay_high)
print(avg_pay_low)


"""
  Name     : c11_14_VaR_500shares_WMT.py
  Book     : Python for Finance (2nd ed.)
  Publisher: Packt Publishing Ltd.
  Author   : Yuxing Yan
  Date     : 6/6/2017
  email    : yany@canisius.edu
             paulyxy@hotmail.com
"""
import numpy as np
import pandas as pd
from scipy.stats import norm
from matplotlib.finance import quotes_historical_yahoo_ochl as getData
#
ticker='WMT'            # input 1
n_shares=500            # input 2
confidence_level=0.99   # input 3
begdate=(2012,1,1)      # input 5
enddate=(2016,12,31)    # input 6
#
z=norm.ppf(confidence_level)
x=getData(ticker,begdate,enddate,asobject=True,adjusted=True)
ret = x.aclose[1:]/x.aclose[:-1]-1
#
position=n_shares*x.close[0]
std=np.std(ret)
#
VaR=position*z*std
print("Holding=",position, "VaR=", round(VaR,4), "tomorrow")


import torch
import math
from math import log10, sqrt
import numpy as np
import torch.nn.functional as F
import cv2

def PSNR(deblurIm, sharpIm):
    """
    Calculates the PSNR of the deblurred image
    using the formula:
    PSNR = 20* log10(maxI/sqrt(mean(delburred image- target image)**2))
    """
    deblurIm = deblurIm.astype(np.float64)
    sharpIm = sharpIm.astype(np.float64)
    mse = np.mean((deblurIm - sharpIm) ** 2)
    # MSE is zero means no noise is present in the signal .
    # Therefore PSNR have no importance.
    if(mse == 0):
        return float('inf')
    max_pixel = 255.0
    psnr = 20 * math.log10(max_pixel / math.sqrt(mse))

    return psnr

def SSIM(deblurIm, sharpIm):
    """
    Calculates the SSIM (The structural similarity index measure) between
    the target image and the deblurred image with:

    SSIM = mean((2*mu_d*mu_s + C1)(2*sig_d_sig_s + C2)/(mu_d^2 + mu_s^2 + C1)(sig_d + sig_s + C2))
    """
    C1 = 0.01 ** 2
    C2 = 0.03 ** 2

    deblurIm = deblurIm.astype(np.float64)
    sharpIm = sharpIm.astype(np.float64)

    filt_ = cv2.getGaussianKernel(11, 1.5)
    filt = np.outer(filt_, filt_.transpose())

    mu_d = cv2.filter2D(deblurIm, -1, filt)[5:-5, 5:-5]
    mu_s = cv2.filter2D(sharpIm, -1, filt)[5:-5, 5:-5]

    mu_d_2 = mu_d**2
    mu_s_2 = mu_s**2
    mu_d_mu_s = mu_d * mu_s

    sig_d = cv2.filter2D(deblurIm**2, -1, filt)[5:-5, 5:-5] - mu_d_2
    sig_s = cv2.filter2D(sharpIm**2, -1, filt)[5:-5, 5:-5] - mu_s_2
    sig_d_sig_s = cv2.filter2D(deblurIm * sharpIm, -1, filt)[5:-5, 5:-5] - mu_d_mu_s

    ssim_ = ((2 * mu_d_mu_s + C1) * (2 * sig_d_sig_s + C2)) / ((mu_d_2 + mu_s_2 + C1) * (sig_d + sig_s + C2))

    ssim = ssim_.mean()

    return ssim


"""Defines vector rotation (lower case) and frame tranformations (upper case).
   Both transformations can be concatenated to be performed in right-to-left
   upon a given vector operator. Note that the *dot()* method must be used,
   since these functions return a 2d *numpy.array* object.
"""

import numpy
from math import sin, cos, atan2

def x(tht_rad):
    """Returns a 3x3 numpy array (matrix) that, when used to multiply a vector
       (using the *dot* method), results in that vector rotated about the x axis
       by the given angle (in radians).
    """
    return numpy.array([
        [1, 0, 0],
        [0, cos(tht_rad), -sin(tht_rad)],
        [0, sin(tht_rad), cos(tht_rad)]])

def y(tht_rad):
    """Returns a 3x3 numpy array (matrix) that, when used to multiply a vector
       (using the *dot* method), results in that vector rotated about the y axis
       by the given angle (in radians).
    """
    return numpy.array([
        [cos(tht_rad), 0, sin(tht_rad)],
        [0, 1, 0],
        [-sin(tht_rad), 0, cos(tht_rad)]])

def z(tht_rad):
    """Returns a 3x3 numpy array (matrix) that, when used to multiply a vector
       (using the *dot* method), results in that vector rotated about the z axis
       by the given angle (in radians).
    """
    return numpy.array([
        [cos(tht_rad), -sin(tht_rad), 0],
        [sin(tht_rad), cos(tht_rad), 0],
        [0, 0, 1]])

def X(tht_rad):
    """Returns a 3x3 numpy array (matrix) that, when used to multiply a vector
       (using the *dot* method), results in that vector evaluated in a new frame
       defined by a rotation about the x axis by the given angle (in radians).
    """
    return numpy.array([
        [1, 0, 0],
        [0, cos(tht_rad), sin(tht_rad)],
        [0, -sin(tht_rad), cos(tht_rad)]])

def Y(tht_rad):
    """Returns a 3x3 numpy array (matrix) that, when used to multiply a vector
       (using the *dot* method), results in that vector evaluated in a new frame
       defined by a rotation about the y axis by the given angle (in radians).
    """
    return numpy.array([
        [cos(tht_rad), 0, -sin(tht_rad)],
        [0, 1, 0],
        [sin(tht_rad), 0, cos(tht_rad)]])

def Z(tht_rad):
    """Returns a 3x3 numpy array (matrix) that, when used to multiply a vector
       (using the *dot* method), results in that vector evaluated in a new frame
       defined by a rotation about the z axis by the given angle (in radians).
    """
    return numpy.array([
        [cos(tht_rad), sin(tht_rad), 0],
        [-sin(tht_rad), cos(tht_rad), 0],
        [0, 0, 1]])

def xyz2sph(xyz):
    """Transforms cartesian coordinates into a spherical coordinate system (with
       polar singularities at +/- z). Returns a 3-component numpy array with
       +z rotation (radians), -y rotation (radians), and radius values.
    """
    xy = (xyz[0]**2 + xyz[1]**2)**0.5
    phi_rad = atan2(xyz[1], xyz[0])
    tht_rad = atan2(xyz[2], xy)
    r = (xyz[0]**2 + xyz[1]**2 + xyz[2]**2)**0.5
    return numpy.array([phi_rad, tht_rad, r])

def sph2xyz(sph):
    """Transforms spherical coordinates into a cartesian coordinates system
       (assuming polar singularities at +/- z). Accepts a 3-component array/list
       with +z rotation (radians), -y rotation (radians), and radius values.
    """
    x = cos(sph[0]) * cos(sph[1])
    y = sin(sph[0]) * cos(sph[1])
    z = sin(sph[1])
    return sph[2] * numpy.array([x, y, z])