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

def get_integer(msg="Number: ", wrng_msg="Invalid Input"):
    try:
        i = int(input(msg))
    except ValueError:
        print(wrng_msg)
        return get_integer(msg, wrng_msg)
    else:
        return i

def get_float(msg="Number: ", wrng_msg="Invalid Input"):
    try:
        f = float(input(msg))
    except ValueError:
        print(wrng_msg)
        return get_float(msg, wrng_msg)
    else:
        return f

def plot_circle():
    print("""
Please enter the radius of circle and the coordinates of its centres in the form "x y", for eg, '3 0'
""")
    x = []
    y = []

    start = 0
    end = 2 * pi
    i = start

    radius = get_float("Radius: ")
    inp = input("Centre coords, default=0,0: ")
    if inp != "":
        cx, cy = inp.split()
        cx, cy = float(cx), float(cy)
    else:
        cx, cy = 0, 0
    resolution = pi / 180

    while i < end + resolution:
        x.append(cx + radius * cos(i))
        y.append(cy + radius * sin(i))
        i += resolution

    plt.plot(x, y)
    plt.plot(cx, cy, "o")
    # legend
    if cx == 0 and cy == 0:
        legends.append(u"x\u00B2 + y\u00B2 = " + str(radius**2))
    elif cx != 0 and cy == 0:
        if cx > 0:
            legends.append(u"(x - " + str(cx) + ")\u00B2 + y\u00B2 = " + str(radius**2))
        else:
            legends.append(u"(x + " + str(-cx) + ")\u00B2 + y\u00B2 = " + str(radius**2))
    elif cx == 0 and cy != 0:
        if cy > 0:
            legends.append(u"x\u00B2 + (y - " + str(cy) + ")\u00B2 = " + str(radius**2))
        else:
            legends.append(u"x\u00B2 + (y + " + str(-cy) + ")\u00B2 = " + str(radius**2))
    else:
        if cx < 0 and cy < 0:
            legends.append(u"(x + " + str(-cx) + ")\u00B2 + (y + " + str(-cy) + ")\u00B2 = " + str(radius**2))
        elif cx > 0 and cy < 0:
            legends.append(u"(x - " + str(cx) + ")\u00B2 + (y + " + str(-cy) + ")\u00B2 = " + str(radius**2))
        elif cx < 0 and cy > 0:
            legends.append(u"(x + " + str(-cx) + ")\u00B2 + (y - " + str(cy) + ")\u00B2 = " + str(radius**2))
        else:
            legends.append(u"(x - " + str(cx) + ")\u00B2 + (y - " + str(cy) + ")\u00B2 = " + str(radius**2))
    legends.append(f"Circle centre({cx}, {cy})")
    print(f"Circle with centre = ({cx}, {cy}) and radius = {radius} plotted!")

def plot_ellipse():
    print("""
To plot an ellipse please give the values of a and b respectively
""")

    start = 0
    end = 2 * pi
    theta = np.linspace(start, end, 360)

    a = get_float("a: ")
    b = get_float("b: ")

    x = a * np.cos(theta)
    y = b * np.sin(theta)

    plt.plot(x, y)
    legends.append(u"x\u00B2/" + str(a**2) + " + y\u00B2/" + str(b**2) + " = 1")
    print(u"Ellipse: x\u00B2/" + str(a**2) + " + y\u00B2/" + str(b**2) + " = 1 plotted!")
    if a < b:
        c = (b**2 - a**2)**0.5
        plt.plot([0, 0], [c, -c], "o")
        legends.append(f"Ellipse foci(0, ±{round(c, 3)})")
    elif a > b:
        c = (a**2 - b**2)**0.5
        plt.plot([c, -c], [0, 0], "o")
        legends.append(f"Ellipse foci(±{round(c, 3)}, 0)")

def plot_quadrilateral():
    inp = get_integer("""
Choose one way...
1. By providing length and breadth,plot rectangle/square, from the origin.
2. By providing coordinates of all four points.
How would you like to proceed(1 or 2): """, "Invalid input, enter either 1 or 2")
    if inp == 1:
        length = get_float("Length: ")
        breadth = get_float("Breadth: ")
        x = [0, length, length, 0, 0]
        y = [0, 0, breadth, breadth, 0]
        if length != breadth:
            legends.append(f"Rectangle(l={length}, b={breadth})")
            print(f"Rectangle(l={length}, b={breadth}) plotted!")
        else:
            legends.append(f"Square(a={length})")
            print(f"Square(a={length}) plotted")
        plt.plot(x, y, 'o-')
    elif inp == 2:
        x = []
        y = []
        print("Enter points in the form 'x y'")
        for i in range(4):
            a, b = input(f"Point {i+1}: ").split()
            a, b = float(a), float(b)
            x.append(a)
            y.append(b)
        x.append(x[0])
        y.append(y[0])
        legends.append(f"Quadrilateral")
        print('Quadrilateral plotted')
        plt.plot(x, y, "o-")
    else:
        print("Invalid input")

def lnr_cnsts(a):
    consts = []
    x1 = -1
    y1 = -1
    if 'x' in a:
        x1 = a.index('x')
    if x1 >= 1:
        l = a[:x1]
    elif x1 == 0:
        l = 1
    else:
        l = 0
    if l == '+':
        l = 1
    elif l == '-':
        l = -1
    l = float(l)
    consts.append(l)
    if 'y' in a:
        y1 = a.index('y')
    if y1 >= 1:
        m = a[x1 + 1:y1]
    elif y1 == 0:
        m = 1
    else:
        m = 0
    if m == '+':
        m = 1
    elif m == '-':
        m = -1
    m = float(m)
    consts.append(m)
    if y1 != -1:
        if len(a) - 1 != y1:
            n = a[y1 + 1:]
        else:
            n = 0
    else:
        if len(a) - 1 != x1:
            n = a[x1 + 1:]
        else:
            n = 0
    n = float(n)
    consts.append(n)
    return consts

def plot_lnreqn():

    print('''
You can get solution of any two pair of linear equations using this program.
Please enter equations in the form "ax + by + c"''')

    en = input('Equation: ')
    eqn = ''
    e = en.split()
    for i in e:
        eqn += i

    constants = lnr_cnsts(eqn)
    a, b, c = constants[0], constants[1], constants[2]
    if a != 0 and b != 0:
        xval = []
        yval = []
        l = 5
        x = (-c) / a
        y = (-c) / b
        if x >= 0:
            end = x + l
            start = -l
        else:
            end = l
            start = x - l
        resolution = 0.01
        i = start
        while i <= end:
            xval.append(i)
            yval.append(((-c) - (a * i)) / b)
            i += resolution
        plt.plot(xval, yval)
        legends.append(eqn)
        plt.plot([x, 0], [0, y], 'o')
        legends.append(u"Soln. to linear eq\u2099")
        print(f"{eqn} plotted!")
    elif a == 0 and b != 0:
        xval = []
        yval = []
        l = 5
        y = (-c) / b
        start = -l
        end = l
        resolution = l
        i = start
        while i <= end:
            xval.append(i)
            yval.append(y)
            i += resolution
        plt.plot(xval, yval)
        legends.append(eqn)
        plt.plot([0], [y], 'o')
        legends.append(u"Soln. to linear eq\u2099")
        print(f"{eqn} plotted!")
    elif a != 0 and b == 0:
        xval = []
        yval = []
        l = 5
        x = (-c) / a
        start = -l
        end = l
        resolution = l
        i = start
        while i <= end:
            xval.append(x)
            yval.append(i)
            i += resolution
        plt.plot(xval, yval)
        legends.append(eqn)
        plt.plot([x], [0], 'o')
        legends.append(u"Soln. to linear eq\u2099")
        print(f"{eqn} plotted!")

def plot_quadratic():
    print(u"""
A quadratic equation is in the form of ax\u00B2 + bx +c = 0. To plot, please provide a, b, c.
""")
    a = get_float("a: ")
    b = get_float("b: ")
    c = get_float("c: ")

    d = (b**2 - (4 * a * c)) ** 0.5
    x1 = ((-b) + d)/(2 * a)
    x2 = ((-b) - d)/(2 * a)

    print(f"Solution to this equation is x = {x1}, {x2}")
    l = 2
    if x1 <= x2:
        start = x1 - l
        end = x2 + l
    else:
        start = x2 - l
        end = x1 + l

    resolution = 0.01
    x = []
    y = []
    i = start
    while i <= end:
        x.append(i)
        y.append((a * (i ** 2)) + (b * i) + c)
        i += resolution

    plt.plot(x, y)
    legends.append(u""+str(a)+"x\u00B2 + " + str(b) + "x + " + str(c))
    plt.plot([x1, x1], [0, 0], "o")
    legends.append("Quadratic equation solution(s)")
    print(u""+str(a)+"x\u00B2 + " + str(b) + "x + " + str(c) + " plotted!")

def plot_polygon():
    print("""
To plot a polygon, provide its points, minimum of 3 to form a polygon.
To give a point, write its coordinates in the form 'x y', eg '3 2'.
Once you are done giving points, just press 'e' and press enter.
""")
    x = []
    y = []
    pointNo = 1
    poly = {3:"Triangle", 4:"Quadrilateral", 5:"Pentagon", 6:"Hexagon", 7:"Septagon", 8:"Octagon", 9:"Nonagon", 10:"Decagon"}
    while True:
        inp = input(f"Point {pointNo}: ")
        if inp.lower() == "e":
            if pointNo >= 4:
                x.append(x[0])
                y.append(y[0])
                break
            else:
                print("Insufficient points to form a polygon")
                pointNo -= 1
        else:
            xval, yval = inp.split()
            xval, yval = float(xval), float(yval)
            x.append(xval)
            y.append(yval)
        pointNo += 1
    plt.plot(x, y, 'o-')
    legends.append(f"{poly.get(pointNo-1, 'Polygon')}")
    print(f"{poly.get(pointNo-1, 'Polygon')} plotted!")

legends = []

while True:
    action = get_integer("""
1. Plot circle
2. Plot ellipse
3. Plot Quadrilateral
4. Plot linear equation in one/two variables
5. Plot quadratic equation
6. Plot polygon
7. Show plotted graph
8. Exit
Choose a action (1-8): """, "Invalid input, please enter the integer code(1-8)")

    if action == 1:
        plot_circle()
    elif action == 2:
        plot_ellipse()
    elif action == 3:
        plot_quadrilateral()
    elif action == 4:
        plot_lnreqn()
    elif action == 5:
        plot_quadratic()
    elif action == 6:
        plot_polygon()
    elif action == 7:
        plt.grid(True)
        leg = input("Would you like to have legends in graph(y/n)(default y)? ").lower()
        if leg == "" or leg == "y" or leg == "yes":
            plt.legend(legends)
        elif leg == "n" or leg == "no":
            pass
        plt.show()
    elif action == 8:
        break
    else:
        print('Invalid input')


import numpy as np
from math import pi, cos, sin, tan

def pad_ones(x, y, z):
    return np.array([x, y, z, np.ones_like(x)])

def normalize(vec):
    return vec / np.linalg.norm(vec)

def project_vector(x, y, z, matrix):
    vec = np.dot(matrix, pad_ones(x, y, z))

    return vec[0]/vec[3], vec[1]/vec[3], vec[2]/vec[3]

def get_look_at_matrix(eye, center, up):
    n = normalize(eye - center)
    u = normalize(np.cross(up, n))
    v = np.cross(n, u)

    matrix_r = [[u[0], u[1], u[2], 0],
                [v[0], v[1], v[2], 0],
                [n[0], n[1], n[2], 0],
                [0,    0,    0,    1]]

    matrix_t = [[1, 0, 0, -eye[0]],
                [0, 1, 0, -eye[1]],
                [0, 0, 1, -eye[2]],
                [0, 0, 0, 1]]

    return np.dot(matrix_r, matrix_t)

def get_perspective_matrix(fovy, aspect, near, far):
    f = 1. / tan(fovy * pi / 360.)

    return np.array([
        [f/aspect, 0,                           0,                           0],
        [       0, f,                           0,                           0],
        [       0, 0,   (near + far)/(near - far), 2 * near * far/(near - far)],
        [       0, 0,                          -1,                           0]
    ])

class OrbitCamera():

    def __init__(self, radius, center, aspect, near=0, far=8):
        self.radius = radius
        self.center = np.array(center)
        self.aspect = aspect
        self.near = near
        self.far = far

        self.update_position(0, 0)

    def update_position(self, elev, azim):
        self.elev = elev
        self.azim = azim

        relev, razim = np.pi * self.elev/180, np.pi * self.azim/180

        xp = self.center[0] + cos(razim) * cos(relev) * self.radius
        yp = self.center[1] + sin(razim) * cos(relev) * self.radius
        zp = self.center[2] + sin(relev) * self.radius

        self.position = np.array((xp, yp, zp))
        self.front = self.center - self.position

        if abs(relev) > pi / 2.:
            self.up = np.array((0, 0, -1))
        else:
            self.up = np.array((0, 0, 1))

        self.update_matrix()

    def update_matrix(self):
        self.view_matrix = get_look_at_matrix(self.position, self.center, self.up)
        self.projection_matrix = get_perspective_matrix(50, self.aspect, self.near, self.far)
        self.matrix = np.dot(self.projection_matrix, self.view_matrix)


import numpy as np
import warnings
from metrics import *

class SimpleLinearRegressor:

    def __init__(self):
        self.betas = None

    def predict(self, X, intercept=True):
        X = np.c_[np.ones(X.shape[0]), X] if intercept else X

        return np.dot(X, self.betas)

    def __ordinary_least_square(self, X, y, **kwargs):
        self.betas = np.dot(np.dot(np.linalg.inv(np.dot(X.T, X)), X.T), y)
        self.is_fitted = True

    def __gradient_descent(self, X, y, learning_rate, steps, seed, verbosity, cost_func='mse', **kwargs):
        np.random.seed(seed)

        minimize = {
            'mse': mean_squared_error,
            'mae': mean_absolute_error,

        }

        self.betas = np.random.rand(X.shape[1])

        for i in range(steps):
            try:
                predicted = self.predict(X, intercept=False)
            except TypeError as e:
                raise Exception('Model is not fitted. Call fit before predict').with_traceback(e.__traceback__)

            try:
                error = minimize.get(cost_func, lambda: 'Invalid')(predicted, y)
            except ValueError as e:
                raise Exception('X and y have different lenght')

            if verbosity != 0 and i % verbosity == 0 :
                print('Step: {} --- Error: {}'.format(i, error))

            error = absolute_error(predicted,  y)
            gradient = 2*np.dot(X.T, error) / len(X)
            self.betas -= learning_rate*gradient

    def fit(self, X, y, mode='ols', learning_rate=0.01, steps=10000, seed=0, verbosity=1000, cost_func='mse'):
        modes = {
            'ols': self.__ordinary_least_square,
            'gradient_descent': self.__gradient_descent
        }

        try:
            X = np.c_[np.ones(X.shape[0]), X]
        except AttributeError as e:
            raise Exception('X must a be an numpy array').with_traceback(e.__traceback__)

        try:
            modes.get(mode)(X=X,
                            y=y,
                            learning_rate=learning_rate,
                            steps=steps,
                            seed=seed,
                            verbosity=verbosity,
                            cost_func=cost_func)

        except TypeError as e:
            modes.get('ols')(X=X,
                            y=y)
            warnings.warn('Invalid parameter was used. Changing to ols and fitting model.'.format(mode))
        except Exception as e:
            raise e


import matplotlib.pyplot as plt
import numpy as np
from scipy.integrate import odeint

import datetime

# Global variables
# speed
move_speed = 0.008

# mackey glass params
sigma = 10.0
phi = 28.0
beta = 8./3.

def runLorenz(num_data_samples=5000):
    # ------ better version on wikipedia which just solves the ODE----
    rho = 28.0
    sigma = 10.0
    beta = 8.0 / 3.0

    def f(state, t):
        x, y, z = state  # unpack the state vector
        # derivatives
        return sigma * (y - x), x * (rho - z) - y, x * y - beta * z

    delta_t = 0.01
    t_end = num_data_samples * delta_t
    state0 = [1.0, 1.0, 1.0]
    t = np.arange(0.0, t_end, delta_t)

    states = odeint(f, state0, t)

    return states

def onExit(data, axis1=0, axis2=2):
    # save the data
    np.savetxt("data_{}.txt".format(datetime.date.today()), data,
               delimiter=",")

    # plot the data
    plt.plot(data[:, axis1], data[:, axis2], linewidth=0.4)
    plt.xlabel("{}".format(axis1))
    plt.ylabel("{}".format(axis2))
    plt.show()

def d_x(x_t, y_t, z_t):
    return sigma * (y_t - x_t)

def d_y(x_t, y_t, z_t):
    return x_t * (phi - z_t) - y_t

def d_z(x_t, y_t, z_t):
    return x_t * y_t - beta * z_t

if __name__ == "__main__":
    data = runLorenz(num_data_samples=20000)
    onExit(data)


#!/usr/bin/env python

# Programmer(s): Sopan Patil.
# This file is part of the 'hydroutils' package.

import numpy

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

class ObjectiveFunction(object):

    """ The 'ObjectiveFunction' class contains the following two commonly used objective functions:
    (1) Kling-Gupta efficiency

    (2) Nash-Sutcliffe efficiency

    """

    @staticmethod
    def klinggupta(obsdata, simdata):

        """ This method calculates Kling-Gupta efficiency
        of the simulated data timeseries.

        Args:
            (1) obsdata: Time series of the observed data.

            (2) simdata: Time series of the simulated data.

        """

        xbar = numpy.mean(obsdata)
        ybar = numpy.mean(simdata)
        nobs = obsdata.shape[0]

        numer = numpy.sum(numpy.multiply(obsdata - xbar, simdata - ybar))
        denom1 = numpy.sum(numpy.square(obsdata - xbar))
        denom2 = numpy.sum(numpy.square(simdata - ybar))

        if denom2 == 0:
            kge = -9999
            return kge

        r = numer/(numpy.sqrt(denom1)*numpy.sqrt(denom2))
        alpha = numpy.sqrt(denom2/nobs)/numpy.sqrt(denom1/nobs)
        beta = ybar/xbar
        kge = 1.0 - numpy.sqrt(numpy.square(r-1.0) + numpy.square(alpha-1.0) + numpy.square(beta-1.0))
        return kge

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

    @staticmethod
    def nashsutcliffe(obsdata, simdata):

        """ This method calculates Nash-Sutcliffe efficiency
        of the simulated data timeseries.

        Args:
            (1) obsdata: Time series of the observed data.

            (2) simdata: Time series of the simulated data.

        """

        numer = numpy.sum(numpy.square(obsdata - simdata))
        denom = numpy.sum(numpy.square(obsdata - numpy.mean(obsdata)))

        nse = 1.0 - (numer/denom)
        return nse

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


import formulas as f
import numpy as np

# Task 1
print("Task 1")

s = np.array([7.0, 7.3, 7.7, 8.1, 8.4, 8.8])
s *= 0.01
in_years = 4

print("Discount rate in {} years is {}".format(in_years, round(f.discount_rate(s[in_years-1], in_years), 3)))

# Task 2
print()
print("Task 2")
s = np.array([7.0, 7.3, 7.7, 8.1, 8.4, 8.8])
s *= 0.01
years = 6

print("Interest rate for {} years of a swap is {}%".format(years, round(100*f.swap_int_rate(s, years), 2)))

# Task 3
print()
print("Task 3")
print("Solution: 118.65")

# Task 4
print()
print("Task 4")
need_contracts = 10
orange_std = 0.2
grape_std = 0.25
corr = 0.7
hedge_ratio = f.futures_hedge_ratio(corr, orange_std, grape_std)
print("Optimal hedging ratio is {}".format(hedge_ratio))
print("Number of contracts to buy is {}".format(round(hedge_ratio*need_contracts, 0)))

# Task 5
print()
print("Task 5")
S0 = 100
u = 1.05
d = 1/u
R = 1.02
K = 102

print("The value of European call option on the stock with strike {} and given parameters"
      "\nS0 = {}"
      "\nu = {}"
      "\nd = {}"
      "\nR = {}"
      "\nis {}".format(K, S0, u, d, R, round(f.options_binomial_model(S0, u, d, R, K), 2)))

# Task 6
print()
print("Task 6")
print("Solution: y in Task 5")


import sympy as sy
from sympy.abc import a,c,b
import matplotlib.pyplot as plt
import numpy as np

def consum_function_plot(function):
    u = function #Original function
    u1d = function.diff(c) #1st derivative
    u2d = function.diff(c,c) #2nd derivative
    u_func, u1d_func, u2d_func = [sy.lambdify((a,c),x) for x in [u, u1d, u2d]] #Convert to lambda functions

    #Numerically solve functions
    x = np.linspace(0,10,101)
    solu_all = []
    for func in [u_func, u1d_func, u2d_func]:
        solu_single = [] #Creates nested list
        for i in x:
            solu_single.append(func(1,i)) #appends to nested list
        solu_all.append(solu_single) #appends nested list to all list

    #Graph
    plt.plot(x,solu_all[0], label='U(c)')
    plt.plot(x,solu_all[1], label=r'$U\prime$')
    plt.plot(x, solu_all[2], label=r'$U\prime\prime$')
    plt.ylabel('U(c)')
    plt.xlabel('c')
    plt.axhline(u_func(1,0), color='red', label=r"$\frac{-1}{a}$")
    plt.legend();

def consum_function_solver(function, time=np.array([1,2])):
    #Functions
    u = function #Original function
    u1d = function.diff(c) #1st derivative
    u2d = function.diff(c,c) #2nd derivative
    u_func, u1d_func, u2d_func = [sy.lambdify((a,c),x) for x in [u, u1d, u2d]] #Convert to lambda functions

    #Numerically solve functions
    x = time
    solu_all = []
    for func in [u_func, u1d_func, u2d_func]:
        solu_single = [] #Creates nested list
        for i in x:
            solu_single.append(func(1,i)) #appends to nested list
        solu_all.append(solu_single) #appends nested list to all list

    return solu_all

def power_euler_nograph(beta=False, r=False, sigma=False):

    beta_r = beta*(1+r)
    euler_rhs = beta_r**sigma

    y1, y2 = [10,10]
    h = y1+(y2/(1+r))
    c1 = h/(1+(beta**sigma*(1+r)**(sigma-1)))
    c2 = (beta*(1+r)**sigma)*(c1)
    return list([c1, c2, euler_rhs])


### Задание 3. Min smooth functions
# f(x) = sin(x / 5) * exp(x / 10) + 5 * exp(-x / 2), на промежутке [1, 30]

import numpy as np
from scipy.optimize import minimize
from plotly.offline import download_plotlyjs, plot, iplot
import plotly
import plotly.graph_objs as go
import math

#1. Попробуйте найти минимум, используя стандартные параметры в функции scipy.optimize.minimize
# (т.е. задав только функцию и начальное приближение).
# Попробуйте менять начальное приближение и изучить, меняется ли результат

def f(x):
    return (math.sin(x/5.)*math.exp(x/10.)+5*math.exp(-x/2.))

f_min1=minimize(f,30)
print ('x=30:', f_min1, '\n')

# 2. Укажите в scipy.optimize.minimize в качестве метода BFGS (один из самых точных в большинстве случаев градиентных методов оптимизации),
# запустите из начального приближения x=2.
# Градиент функции при этом указывать не нужно – он будет оценен численно.
f_min2=minimize(f,2, method = 'BFGS')
print ('x=2:',f_min2, '\n')

# 3. Теперь измените начальное приближение на x=30.
f_min3=minimize(f,30, method = 'BFGS')
print ('x=30:',f_min3,'\n')

# 4. Построение графика

x=np.arange(1,31,0.1)
trace=go.Scatter(
    x=x,
    y=list(map(f,x))
)
fig=go.Figure(data=[trace])
iplot(fig, show_link=False)
plot(fig, filename="min_smoothness.html", show_link=False)


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

# Adapted to use numpy array as entry from https://github.com/chncyhn/simulated-annealing-tsp

class SimAnneal(object):
    def __init__(self, Mw, T=-1, alpha=-1, stopping_T=-1, stopping_iter=-1):
        self.N = Mw.shape[0]
        self.T = math.sqrt(self.N) if T == -1 else T
        self.alpha = 0.995 if alpha == -1 else alpha
        self.stopping_temperature = 0.00000001 if stopping_T == -1 else stopping_T
        self.stopping_iter = 100000 if stopping_iter == -1 else stopping_iter
        self.iteration = 1

        self.dist_matrix = Mw
        self.nodes = [i for i in range(self.N)]

        self.cur_solution = self.initial_solution()
        self.best_solution = list(self.cur_solution)

        self.cur_fitness = self.fitness(self.cur_solution)
        self.initial_fitness = self.cur_fitness
        self.best_fitness = self.cur_fitness

        self.fitness_list = [self.cur_fitness]

    def initial_solution(self):
        """
        Greedy algorithm to get an initial solution (closest-neighbour)
        """
        cur_node = random.choice(self.nodes)
        solution = [cur_node]
        free_list = list(self.nodes)
        free_list.remove(cur_node)

        while free_list:
            closest_dist = np.amin(self.dist_matrix[cur_node,free_list])
            #np.where returns a list with indexes containing the closest_dist (which may be duplicated), intersect that with indexes still available (free_list) and get the first index available containing the closest_dist
            cur_node = np.intersect1d(np.where(self.dist_matrix[cur_node] == closest_dist)[0], np.array(free_list))[0]
            free_list.remove(cur_node)
            solution.append(cur_node)

        return solution

    def fitness(self, sol):
        """ Objective value of a solution """
        return round(sum([self.dist_matrix[sol[i - 1],sol[i]] for i in range(1, self.N)]) +
                     self.dist_matrix[sol[self.N - 1],sol[0]], 6)

    def p_accept(self, candidate_fitness):
        """
        Probability of accepting if the candidate is worse than current
        Depends on the current temperature and difference between candidate and current
        """
        return math.exp(-abs(candidate_fitness - self.cur_fitness) / self.T)

    def accept(self, candidate):
        """
        Accept with probability 1 if candidate is better than current
        Accept with probabilty p_accept(..) if candidate is worse
        """
        candidate_fitness = self.fitness(candidate)
        if candidate_fitness < self.cur_fitness:
            self.cur_fitness = candidate_fitness
            self.cur_solution = candidate
            if candidate_fitness < self.best_fitness:
                self.best_fitness = candidate_fitness
                self.best_solution = candidate

        else:
            if random.random() < self.p_accept(candidate_fitness):
                self.cur_fitness = candidate_fitness
                self.cur_solution = candidate

    def anneal(self):
        """
        Execute simulated annealing algorithm
        """
        while self.T >= self.stopping_temperature and self.iteration < self.stopping_iter:
            candidate = list(self.cur_solution)
            l = random.randint(2, self.N - 1)
            i = random.randint(0, self.N - l)
            candidate[i:(i + l)] = reversed(candidate[i:(i + l)])
            self.accept(candidate)
            self.T *= self.alpha
            self.iteration += 1
            self.fitness_list.append(self.cur_fitness)


import numpy as np

def f(x):
    return 20*x**1.5+np.exp(-x/5)

n=int(input("Number of panels: "))
sum = float()
if n%2!=0:
    print("Error.")
    quit()
else:
    x1=float(input("xmin: "))
    x2=float(input("xmax: "))
    h = (x2 - x1) / n
    for i in range(0,n):
        if i==0:
            x = x1
            y = f(x)
            sum = y
            print("x:","%.5f" % x); print("y:","%.5f" % y); print()
        else:
            x = x1 + h*i
            y = f(x)
            if i%2==0:
                sum = sum + 2*y
            else:
                sum = sum + 4*y
            print("x:","%.5f" % x); print("y:","%.5f" % y); print()
    x = x2
    y = f(x)
    sum = sum + y
    print("x:","%.5f" % x); print("y:","%.5f" % y); print()
    sum = h * sum/3
    print("SUM=","%.5f" % sum)


"""
Some study code for BSpline operation

Ref:
    [1] L. Biagiotti and C. Melchiorri, Trajectory Planning for Automatic Machines and Robots. 2008.
"""

import os
import sys

sys.path.append(os.path.abspath(os.path.join(__file__, os.pardir)))
sys.path.append(os.path.abspath(os.path.join(__file__, os.pardir, os.pardir)))

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

# class BSpline:
#     """
#     BSpline
#     """

#     def __init__(self, degree:)

def basic(knots: np.ndarray, degree: int, u: float, index: int):
    """
    Calculate the basic function in BSpline, N(i, p, u)

    Args:
        knots (np.ndarray): Knots vector {u}
        degree (int): Degree p
        u (float): Evaluate input u
        index (int): The index of u, i

    Returns:
        float: Basic function result evaluated at u
    """
    if degree == 0:
        return 1.0 if knots[index] <= u < knots[index + 1] else 0.0

    if knots[index] > u or u >= knots[index + degree + 1]:
        return 0

    c1 = (u - knots[index]) / (knots[index + degree] - knots[index]) if knots[index] <= u < knots[index +
                                                                                degree] else 0.0
    c2 = (knots[index + degree + 1] - u) / (
        knots[index + degree + 1] - knots[index + 1]) if knots[index + 1] <= u < knots[index + degree + 1] else 0.0
    return c1 * basic(knots, degree - 1, u, index) + c2 * basic(knots, degree - 1, u, index + 1)

def bspline(knots: np.ndarray, ctrl_points: np.ndarray, degree: int, u: float):
    """
    Evaluate BSpline function at u

    Args:
        knots (np.ndarray): Knots vector {u}
        ctrl_points (np.ndarray): Control points {P}
        degree (int): Degree p
        u (float): Evaluate input u
    Returns:
        np.ndarray:
    """
    s = np.zeros(ctrl_points.shape[0])
    for m in range(ctrl_points.shape[0]):
        for n in range(ctrl_points.shape[1]):
            s[m] += basic(knots, degree, u, n) * ctrl_points[m, n]
    return s

def cal_basic():
    """
    Calculate the basic function
    """
    print(util.Section('Basic Function'))

    # evaluate of degree 1
    knots = np.array([0.0, 0, 1, 2, 4, 7, 7])
    degree = 1
    u_array = np.arange(knots.min(), knots.max(), 0.01)
    basic_array = np.zeros([7, u_array.shape[0]])
    for n, u in enumerate(u_array):
        for j in range(0, basic_array.shape[0]):
            basic_array[j, n] = basic(knots, degree, u, j)
    # plot
    fig = plt.figure(f'Basic Function of Degree {degree}')
    ax = fig.add_subplot(111)
    ax.grid(True)
    for j in range(0, basic_array.shape[0]):
        ax.plot(u_array, basic_array[j, :], label=f'$B_{{{j}{degree}}}$')
    ax.legend(loc='best')
    ax.set_title(f'Basic function of Degree 1 Defined on u = {knots}')

    # evaluate of degree 3
    knots = np.array([0.0, 0, 0, 0, 1, 2, 4, 7, 7, 7, 7])
    degree = 3
    u_array = np.arange(knots.min(), knots.max(), 0.01)
    basic_array = np.zeros([7, u_array.shape[0]])
    for n, u in enumerate(u_array):
        for j in range(0, basic_array.shape[0]):
            basic_array[j, n] = basic(knots, degree, u, j)
    # plot
    fig = plt.figure(f'Basic Function of Degree {degree}')
    ax = fig.add_subplot(111)
    ax.grid(True)
    for j in range(0, basic_array.shape[0]):
        ax.plot(u_array, basic_array[j, :], label=f'$B_{{{j}{degree}}}$')
    ax.legend(loc='best')
    ax.set_title(f'Basic function of Degree 1 Defined on u = {knots}')

def cal_bspline():
    """
    Calculate the BSpline function
    """
    print(util.Section('BSpline Function'))

    # Evaluation case 1
    knots = np.array([0.0, 0, 0, 0, 1, 2, 4, 7, 7, 7, 7.0])
    ctrl_points = np.array([[1, 2, 3, 4, 5, 6, 7], [2, 3, -3, 4, 5, -5, -6]])
    degree = 3
    u_array = np.arange(knots.min(), knots.max(), 0.01)
    bspline_array = np.zeros([ctrl_points.shape[0], u_array.shape[0]])
    for n, u in enumerate(u_array):
        bspline_array[:, n] = bspline(knots, ctrl_points, degree, u)
    # plot
    fig = plt.figure(f'Basic Function of Degree {degree} - Case 1')
    ax = fig.add_subplot(111)
    ax.grid(True)
    ax.plot(ctrl_points[0, :], ctrl_points[1, :], 'o--')
    ax.plot(bspline_array[0, :], bspline_array[1, :])
    ax.set_title(f'BSpline function of Degree {degree} Defined on u = {knots}')

    # Evaluation case 2, double the knots in case 1
    knots2 = 2 * knots
    ctrl_points = np.array([[1, 2, 3, 4, 5, 6, 7], [2, 3, -3, 4, 5, -5, -6]])
    degree = 3
    u_array2 = np.arange(knots2.min(), knots2.max(), 0.01)
    bspline_array2 = np.zeros([ctrl_points.shape[0], u_array2.shape[0]])
    for n, u in enumerate(u_array2):
        bspline_array2[:, n] = bspline(knots2, ctrl_points, degree, u)
    # plot
    fig = plt.figure(f'Basic Function of Degree {degree} - Double the Knots')
    ax = fig.add_subplot(111)
    ax.grid(True)
    ax.plot(u_array, bspline_array[0, :], label='BSpline1[0]')
    ax.plot(u_array, bspline_array[1, :], label='BSpline1[1]')
    ax.plot(u_array2, bspline_array2[0, :], label='BSpline2[0]')
    ax.plot(u_array2, bspline_array2[1, :], label='BSpline2[1]')
    ax.legend(loc='best')
    ax.set_title(f'BSpline function of Degree {degree} Defined on u = {knots}')

    # Evaluation case 3
    knots = np.array([0.0, 0, 0, 0, 2, 2, 2, 7, 7, 7, 7.0])
    ctrl_points = np.array([[1, 2, 3, 4, 5, 6, 7], [2, 3, -3, 4, 5, -5, -6]])
    degree = 3
    u_array = np.arange(knots.min(), knots.max(), 0.01)
    bspline_array = np.zeros([ctrl_points.shape[0], u_array.shape[0]])
    for n, u in enumerate(u_array):
        bspline_array[:, n] = bspline(knots, ctrl_points, degree, u)
    # plot
    fig = plt.figure(f'Basic Function of Degree {degree} - Case 3')
    ax = fig.add_subplot(111)
    ax.grid(True)
    ax.plot(ctrl_points[0, :], ctrl_points[1, :], 'o--')
    ax.plot(bspline_array[0, :], bspline_array[1, :], label='BSpline1')
    ax.legend(loc='best')
    ax.set_title(f'BSpline function of Degree {degree} Defined on u = {knots}')

    # Evaluation case 4, for different degree
    knots = np.array([0.0, 0, 0, 0, 1, 2, 4, 7, 7, 7, 7])
    ctrl_points = np.array([[1, 2, 3, 4, 5, 6, 7], [2, 3, -3, 4, 5, -5, -6]])
    degree = 3
    u_array = np.arange(knots.min(), knots.max(), 0.01)
    bspline_array = np.zeros([ctrl_points.shape[0], u_array.shape[0]])
    bspline_array2 = np.zeros([ctrl_points.shape[0], u_array.shape[0]])
    bspline_array3 = np.zeros([ctrl_points.shape[0], u_array.shape[0]])
    for n, u in enumerate(u_array):
        bspline_array[:, n] = bspline(knots, ctrl_points, degree, u)
        bspline_array2[:, n] = bspline(knots, ctrl_points, degree - 1, u)
        bspline_array3[:, n] = bspline(knots, ctrl_points, degree - 2, u)
    # plot
    fig = plt.figure(f'Basic Function of Degree {degree} to {degree-2} - Case 3')
    ax = fig.add_subplot(111)
    ax.grid(True)
    ax.plot(ctrl_points[0, :], ctrl_points[1, :], 'o--')
    ax.plot(bspline_array[0, :], bspline_array[1, :], label='BSpline1')
    ax.plot(bspline_array2[0, :], bspline_array2[1, :], label='BSpline2')
    ax.plot(bspline_array3[0, :], bspline_array3[1, :], label='BSpline3')
    ax.legend(loc='best')
    ax.set_title(f'BSpline function of Degree {degree} to {degree-2} Defined on u = {knots}')

def main():
    # cal_basic()
    cal_bspline()
    plt.show(block=True)

if __name__ == "__main__":
    main()


from __future__ import division
from scipy import *
from pylab import *

from scipy import signal

T=2.0
#T=10.0
fs=100
dt=1.0/fs
t=arange(0.0,T,dt)#create the time vector
u=where(t>0.5,1,0)#create the step input vector

ylim([-0.1,1.1])
#mysys=signal.lti(1,[1,0])
p=4.0*2*pi
mysys=signal.lti(p,[1,p])#this line defines a transfer function
yo=signal.lsim2(mysys,u,t)#this line simulates the output of the system based on input u and time t
u=squeeze(u)
figure(1)
cla()
plot(t,u,t,yo[1])
legend(['input','output'],2)
xlabel('Time (sec)')
ylabel('Amplitude')
title('Step Response')

df=1.0/T#(t.max()-t.min())
f=arange(0,fs,df)

s=2.0j*pi*f

#tf=1.0/s

N=len(f)

def bodeplot(fi,f,tf,clear=True):
    figure(fi)
    if clear:
        clf()
    subplot(211)
    semilogx(f,20*log10(abs(tf)))
    ylabel('Mag. Ratio (dB)')
    subplot(212)
    semilogx(f,arctan2(imag(tf),real(tf))*180.0/pi)
    ylabel('Phase (deg.)')
    xlabel('Freq. (Hz)')

#################################
#
#    Swept Sine
#
#################################
def Usweep(ti,minf=0.0,maxf=10.0, maxt=max(t)):
    if ti<0.0:
        return 0.0
    else:
        curf=(maxf-minf)*ti/maxt+minf
        if ti<(maxt*0.95):
            return sin(2*pi*curf*ti)
        else:
            return 0.0

Uchirp=array([Usweep(ti) for ti in t])#this line defins a swept sine input
yc=signal.lsim2(mysys,Uchirp,t)#this line calculates the response to the swept sine input
Uchirp=squeeze(Uchirp)
yco=yc[1]

figure(3)
clf()
subplot(211)
plot(t,Uchirp)
ylabel('input u(t)')
title('Swept Sine Response')
subplot(212)
plot(t,yco)
ylabel('output y(t)')
xlabel('Time (sec)')

ycfft=fft(yco)*2/N
ucfft=fft(Uchirp)*2/N
tfc=ycfft/ucfft

tfcheck=p/(s+p)

bodeplot(4,f,tfc)
bodeplot(4,f,tfcheck,clear=False)

fN=f[int(N/2)]
subplot(211)
xlim([0.1,fN])
legend(['experiment','model'],3)
title('Bode Plot')

subplot(212)
xlim([0.1,fN])
ylim([-100,10])

show()


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

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

times = pd.read_csv('servicetime_data.csv')
x = times['ser_time'].values
xvalues = list(x)

times.plot.hist(bins=150)
plt.xlabel('Service Time')
plt.ylabel('Frequency')
plt.show()

logx = np.log(x)

# MLE for Exponential:
rate = len(x)/float(x.sum()) # lambda = n/sum(x)
scale1 = 1.0/rate
loc = 0

# create a Q-Q plot
fig1 = stats.probplot(x, dist="expon", sparams=(loc,scale1), plot=plt)
plt.show()

# perform a goodness of fit test (K-S) test;
# null hyposthesis is that data is coming from the specified dist
GoF1 = stats.kstest(x, 'expon', args=(loc, scale1))
print GoF1

# MLE for Lognormal:
mu = logx.sum()/len(x)
sigma = np.sqrt(((logx-(logx.sum()/len(x)))**2).sum()/len(x))
shape2 = sigma
scale2 = np.exp(mu)
loc = 0

fig2 = stats.probplot(x, dist="lognorm", sparams=(shape2,loc,scale2), plot=plt)
plt.show()

GoF2 = stats.kstest(x, 'lognorm', args=(shape2, loc, scale2))
print GoF2

# Gamma:
# Since there is no closed form MLE for Gama, we fit a Gamma numerically
shape3, loc, scale3 = stats.gamma.fit(x, floc = 0)

fig3 = stats.probplot(x, dist="gamma", sparams=(shape3,loc,scale3), plot=plt)
plt.show()

GoF3 = stats.kstest(xvalues, 'gamma', args=(shape3, loc, scale3))
print GoF3

# Moments estimation for Gama:
beta = x.std()
alpha = x.mean()/x.std()


import numpy as np

def randInitializeWeights(L_in, L_out):
#RANDINITIALIZEWEIGHTS Randomly initialize the weights of a layer with L_in
#incoming connections and L_out outgoing connections
#   W = RANDINITIALIZEWEIGHTS(L_in, L_out) randomly initializes the weights
#   of a layer with L_in incoming connections and L_out outgoing
#   connections.
#
#   Note that W should be set to a matrix of size(L_out, 1 + L_in) as
#   the first row of W handles the "bias" terms
#

# You need to return the following variables correctly
    W = np.zeros((L_out, 1 + L_in))

# ====================== YOUR CODE HERE ======================
# Instructions: Initialize W randomly so that we break the symmetry while
#               training the neural network.
#
# Note: The first row of W corresponds to the parameters for the bias units

    epsilon = np.sqrt(6)/np.sqrt(L_out + L_in)
    s = np.random.uniform(-epsilon, epsilon, L_out * (1 + L_in))
    W = s.reshape(L_out, 1 + L_in)

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

    return W


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Tue Jul  9 11:48:56 2019

@author: fietekrutein

A script to solve an unconstrained problem using
steepest descent fradient search with exact line search
"""
import numpy as np
import matplotlib.pyplot as plt

# functions as per example problem

def obj(x,Q):
    return 0.5*np.matmul(x, np.matmul(Q,x))

def gx2(x,Q):
    return np.matmul(Q,x)

# method

def GradDescent2(x,Q,gx2,rec,tol=10e-5):
    xCurrent = x
    gxVal = gx2(xCurrent,Q)
    rec.append(obj(xCurrent,Q))
    while True:
        xNext = xCurrent - ((xCurrent[0]**2 + gamma[i]**2*xCurrent[1]**2)/
                            (xCurrent[0]**2 + gamma[i]**3*xCurrent[1]**2))*gxVal
        gxNextVal = gx2(xNext, Q)
        rec.append(obj(xNext,Q))

        if (np.linalg.norm(gxNextVal,2) <= tol) == True:
            break
        xCurrent = xNext
        gxVal = gxNextVal

    return xNext, rec

# initialize problem parameters
gamma = np.array([0.1, 1, 2, 10])
rec = np.empty(4, dtype=np.object)

# execute

for i in np.arange(0,4):
    x = np.array([gamma[i], 1])
    Q = np.array([[1,0],[0,gamma[i]]])
    rec[i] = []
    GradDescent2(x, Q, gx2, rec[i], tol=10e-5)

# plot

plt.subplot(2,2,1)
plt.plot(rec[0])
plt.xlabel('iterations')
plt.ylabel('objective value')
plt.subplot(2,2,2)
plt.plot(rec[1])
plt.xlabel('iterations')
plt.subplot(2,2,3)
plt.plot(rec[2])
plt.xlabel('iterations')
plt.ylabel('objective value')
plt.subplot(2,2,4)
plt.plot(rec[3])
plt.xlabel('iterations')

plt.show()


## module romberg
''' I,nPanels = romberg(f,a,b,tol=1.0e-6).
    Romberg intergration of f(x) from x = a to b.
    Returns the integral and the number of panels used.
'''
from numpy import zeros
from trapezoid import *

def romberg(f,a,b,tol=1.0e-6):

    def richardson(r,k):
        for j in range(k-1,0,-1):
            const = 4.0**(k-j)
            r[j] = (const*r[j+1] - r[j])/(const - 1.0)
        return r

    r = zeros(21)
    r[1] = trapezoid(f,a,b,0.0,1)
    r_old = r[1]
    for k in range(2,21):
        r[k] = trapezoid(f,a,b,r[k-1],k)
        r = richardson(r,k)
        if abs(r[1]-r_old) < tol*max(abs(r[1]),1.0):
            return r[1],2**(k-1)
        r_old = r[1]
    print("Romberg quadrature did not converge")

ExamPrep/SciCompComplete/Shit Comp/Cheat Sheet + Modules/romberg.py


"""
  Name     : c9_08_generate_2set_correlated_randomNumbers.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 scipy as sp
sp.random.seed(123)
n=1000
rho=0.3

x1=sp.random.normal(size=n)
x2=sp.random.normal(size=n)

y1=x1
y2=rho*x1+sp.sqrt(1-rho**2)*x2
print(sp.corrcoef(y1,y2))


import matplotlib.pyplot as plt
from numpy import loadtxt, zeros, ones, array, linspace, logspace
from pylab import scatter, show, title, xlabel, ylabel, plot, contour, legend
from LinearRegression import LinearRegression
import numpy as np
from matplotlib.colors import Normalize
from matplotlib import cm
from mpl_toolkits.mplot3d import axes3d, Axes3D

LR = LinearRegression()

def surf(Z, X, Y):

    C = Z

    scalarMap = cm.ScalarMappable(norm=Normalize(
        vmin=C.min(), vmax=C.max()), cmap=cm.jet)

    # outputs an array where each C value is replaced with a corresponding color value
    C_colored = scalarMap.to_rgba(C)

    fig = plt.figure()

    ax = Axes3D(fig)

    surf = ax.plot_surface(X, Y, Z, facecolors=C_colored)

    return surf

# ====================Part 1: Basic Function====================

print('Running warmUpExercise ...')
print('5x5 Identity Matrix:')
print(LR.warmupex())

input('Program paused. Press enter to continue.')

# ========================Part 2: Plotting======================

print('plotting data')
data = np.loadtxt('ex1data1.txt', delimiter=',')
datax = data[:, 0]
datay = data[:, 1]
m = len(datay)  # number of training examples
datax = data[:, 0].reshape((m, 1))
datay = data[:, 1].reshape((m, 1))
# LR.plotdata(datax, datay)

input('Program paused. Press enter to continue.')

# =============Part 3: Cost and Gradient descent================

# Add a column of ones to x

one = np.ones((m, 1))
datax = np.append(one, datax, axis=1)
print(datax)
print(datax.shape)
# initialize fitting parameters

theta = np.zeros((2, 1))

# Some gradient descent settings
alpha = 0.01
num_iters = 1500
print('Testing the cost function ...')

# compute and display initial cost

J = LR.computecost(datax, datay, theta)
print('With theta = [0 ; 0]Cost computed =', J)
print('Expected cost value (approx) 32.07')

# further testing of the cost function

thetatest = np.array([[-1], [2]])
J = LR.computecost(datax, datay, thetatest)
print('With theta = [-1 ; 2]Cost computed = ', J)
print('Expected cost value (approx) 54.24')

input('Program paused. Press enter to continue.')

# run gradient descent

print('Running Gradient Descent ...')
theta, J_history = LR.gradientdescent(datax, datay, theta, alpha, num_iters)
# plot(list(range(num_iters)), J_history)
# show()
# print theta to screen

print('Theta found by gradient descent:')
print('  ', theta)
print('Expected theta values (approx)')
print(' -3.6303  1.1664')

# Plot the linear fit
# hold on; % keep previous plot visible

scatter(datax[:, 1], datax.dot(theta))
xlabel('Training data')
ylabel('Linear regression')
show()

# Predict values for population sizes of 35, 000 and 70, 000
predict1 = np.dot([1, 3.5], theta)
print('For population = 35,000, we predict a profit of ', predict1*10000)
predict2 = np.dot([1, 7], theta)
print('For population = 70,000, we predict a profit of ', predict2*10000)

input('Program paused. Press enter to continue.')

# =============Part 4: Visualizing J(theta_0, theta_1)=============

print('Visualizing J(theta_0, theta_1) ')

# Grid over which we will calculate J

theta0_vals = np.linspace(-10, 10, 100)
theta1_vals = np.linspace(-1, 4, 100)

# initialize J_vals to a matrix of 0's

J_vals = zeros(shape=(theta0_vals.size, theta1_vals.size))

# Fill out J_vals

for i in range(0, len(theta0_vals)):

    for j in range(0, len(theta1_vals)):
        t = [[theta0_vals[i]], [theta1_vals[j]]]
        J_vals[i, j] = LR.computecost(datax, datay, t)

print(J_vals)

X, Y = np.meshgrid(theta0_vals, theta1_vals)

# Because of the way meshgrids work in the surf command, we need to
# transpose J_vals before calling surf, or else the axes will be flipped

J_vals = np.transpose(J_vals)

# Surface plot
surf(X=X, Y=Y, Z=J_vals)
fig2 = plt.figure(figsize=(6, 5))
# Contour plot

input('press enter ')

contour(theta0_vals, theta1_vals, J_vals, np.logspace(-2, 3, 20))
xlabel('theta_0')
ylabel('theta_1')
scatter(theta[0], theta[1])
show()

input('press inter ')

legend(loc='lower right')
show()
print(theta)


import numpy as np
from datetime import datetime
startTime = datetime.now()

max_prime = 2000000
primes = range(2,max_prime)
length = len(primes)

for idx in range(len(primes)):
    p = primes[idx]
    if p == 0:
        continue

    # No multiples of any prime is a prime
    for i in range(2, (length + 1) / p + 1):
        primes[p*i - 2] = 0

primes = [y for y in primes if y != 0]

print "Time to make list", datetime.now() - startTime

print 'sum_of_primes less than', max_prime,':', np.sum(primes)


# -*- coding: utf-8 -*-
"""
Created on Sat Jun  2 23:33:19 2018

@author: Marcus
"""

import numpy as np

def generate_W_N_table(N):
    """Generate a table of phase angles.

    Parameters
    ----------
    N : int
        The number of phase angles needed. Must be a power of 2.

    Returns
    -------
    np.array
        An array of the phase angles.
    """
    if((N % 2) != 0):
        raise ValueError("N must be a power of 2")

    elif(N <= 0):
        raise ValueError("N must be a positive integer")

    W_N = np.zeros(N, dtype=np.complex)

    W = np.exp(-1j * 2 * np.pi / N)

    for idx in range(N//2):
        W_N[idx] = np.power(W, idx)

    W_N[N//2:] = -1 * W_N[:N//2]

    return W_N

N = 4

x = np.random.normal(size=N)

W = generate_W_N_table(N)

X = np.fft.fft(x)

y = np.fft.ifft(X)

my_X = np.zeros(N, dtype=np.complex)
first_stage = np.zeros(N, dtype=np.complex)

#2-point DFTs
W_2 = np.array([W[0], W[0]])
a = x[0:2]
b = W_2 * x[2:4]

first_stage[0] = a[0] + b[0]
first_stage[1] = a[0] - b[0]
first_stage[2] = a[1] + b[1]
first_stage[3] = a[1] - b[1]

#4-point DFT
W_4 = np.array([W[0], W[1]])
A = first_stage[0:2]
B = W_4 * first_stage[2:4]

my_X[0] = A[0] + B[0]
my_X[1] = A[1] + B[1]
my_X[2] = A[0] - B[0]
my_X[3] = A[1] - B[1]

print(X)
print(my_X)
print(np.allclose(X, my_X))


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Tue Jul 21 12:04:44 2020

Here are stored functions which return derivatives of certain values
things like Jacobians, Hessians, Flows and Nablas are defined here

import statement for ease of reference:
from kep_derivative_functions import nabla_lin_y,nabla_lin_x,nabla_l,nabla_q,nabla_H
from kep_derivative_functions import partial_Hqqq,partial_Hpp,partial_Hqq,hessian_H
from kep_derivative_functions import gradient,modified_gradient_en_ang_attractor,modified_gradient_energy_attractor

@author: steve
"""

import numpy as np
import math
from kep_util_globvar import G,M1,M2,ETA,ENERGY_0,TOTAL_ANG_MOMENTUM_0
from kep_util_globvar import normsq,supervec_norm
from kep_util_globvar import get_energy,get_total_angular_momentum

# %% GRADIANT FUNCTIONS, GRADIENTS OF FIRST INTEGRALS (NABLA)

# returns y' = J^{-1}\nabla H given y
# y is [p1,p2,q1,q2]
def gradient(y):
    # assume 2 body problem
    # here gradient is a bit of misnomer, it's the J^{-1}\nabla H that I label grad y
    r = np.array([y[2][0]-y[3][0] , y[2][1]-y[3][1]])#r from 1 to 0
    rabs = np.sqrt(normsq(r))
    grady = []
    grady.append(-r*G*M1*M2*(rabs**(-3)))
    grady.append(r*G*M1*M2*(rabs**(-3)))
    grady.append(y[0]/M1)
    grady.append(y[1]/M2)
    return np.array(grady)

# uses ENERGY_0 turns the energy manifold into an attractor
def modified_gradient_energy_attractor(y):
    r = np.array([y[2][0]-y[3][0] , y[2][1]-y[3][1]])#r from 1 to 0
    rabs = np.sqrt(normsq(r))
    grady = []
    grady.append(-r*G*M1*M2*(rabs**(-3)))
    grady.append(r*G*M1*M2*(rabs**(-3)))
    grady.append(y[0]/M1)
    grady.append(y[1]/M2)
    grady = np.array(grady)
    # an attracive term is added along nabla H
    energy_y = get_energy(y)
    attracting_term = nabla_H(y)
    # attracting_term = attracting_term / supervec_norm(attracting_term)
    attracting_term *= (ENERGY_0 - energy_y) * math.exp(ENERGY_0 - energy_y) /5

    return grady + attracting_term

# additionall attracting term to the ENERGY_0 and ANGULAR_M_0 manifolds
def modified_gradient_en_ang_attractor(y):
    r = np.array([y[2][0]-y[3][0] , y[2][1]-y[3][1]])#r from 1 to 0
    rabs = np.sqrt(normsq(r))
    grady = []
    grady.append(-r*G*M1*M2*(rabs**(-3)))
    grady.append(r*G*M1*M2*(rabs**(-3)))
    grady.append(y[0]/M1)
    grady.append(y[1]/M2)
    grady = np.array(grady)
    n_grady = math.sqrt(supervec_norm(grady))
    # an attractive term as in the naive approach, first energy
    energy_y = get_energy(y)
    energy_attracting_term = nabla_H(y)
    energy_attracting_term *= (ENERGY_0 - energy_y) * math.exp(ENERGY_0 - energy_y)
    e_att_n = np.sqrt(supervec_norm(energy_attracting_term))
    # make the attracting term smaller than the initial term (1/10th at most)
    if e_att_n * 10 > n_grady:
        energy_attracting_term *= n_grady / (10 * e_att_n)
    # then angular momentum
    ang_y = get_total_angular_momentum(y)
    ang_attracting_term = nabla_l(y)
    ang_attracting_term *= (TOTAL_ANG_MOMENTUM_0 - ang_y) * math.exp(TOTAL_ANG_MOMENTUM_0 - ang_y)
    ang_att_n = np.sqrt(supervec_norm(energy_attracting_term))
    # make the attracting term smaller if it's too big
    if ang_att_n * 10 > n_grady:
        ang_attracting_term *= n_grady / (10 * e_att_n)

    return grady + energy_attracting_term + ang_attracting_term

# returns the gradient of the hamiltonian
def nabla_H(y):
    r = np.array([y[2][0]-y[3][0] , y[2][1]-y[3][1]])# r from 1 to 0
    rabs = np.sqrt(normsq(r))
    nabla_h = []
    nabla_h.append(y[0]/M1)
    nabla_h.append(y[1]/M2)
    nabla_h.append(r*G*M1*M2*(rabs**(-3)))
    nabla_h.append(-r*G*M1*M2*(rabs**(-3)))
    return np.array(nabla_h)

# returns the hessian matrix of the hamiltonian at y
def hessian_H(y):
    # see section 3.1 kepler problem in report write-up
    # compute xi1 and xi2
    xi = math.sqrt(np.dot(y[2]-y[3],y[2]-y[3]))
    xito3 = xi**3
    xito5 = xi**5
    xi1 = y[3][0] - y[2][0]
    xi2 = y[3][1] - y[2][1]
    # we define each column manually (also symmetric so columns = rows), it's only eight by eight
    col1 = (1/M1,0,0,0,0,0,0,0)
    col2 = (0,1/M1,0,0,0,0,0,0)
    col3 = (0,0,1/M2,0,0,0,0,0)
    col4 = (0,0,0,1/M2,0,0,0,0)
    col5 = (0,0,0,0, -ETA/xito3 + ETA/xito5*xi1**2 , ETA/xito5*xi1*xi2 , ETA/xito3 - ETA/xito5*xi1**2 , -ETA/xito5*xi1*xi2)
    col6 = (0,0,0,0, ETA/xito5*xi1*xi2 , -ETA/xito3 + ETA/xito5*xi2**2 , -ETA/xito5*xi1*xi2 , ETA/xito3 - ETA/xito5*xi2**2)
    col7 = (0,0,0,0, ETA/xito3 - ETA/xito5*xi1**2 , -ETA/xito5*xi1*xi2 , -ETA/xito3 + ETA/xito5*xi1**2 , ETA/xito5*xi1*xi2)
    col8 = (0,0,0,0, -ETA/xito5*xi1*xi2 , ETA/xito3 - ETA/xito5*xi2**2 , ETA/xito5*xi1*xi2 , -ETA/xito3 + ETA/xito5*xi2**2)
    return np.array((col1,col2,col3,col4,col5,col6,col7,col8))

# returns 4x4 matrix, lower right hand block of hessian
def partial_Hqq(y):
    # see section 3.1 kepler problem in report write-up
    # compute xi1 and xi2
    xi = math.sqrt(np.dot(y[2]-y[3],y[2]-y[3]))
    xito3 = xi**3
    xito5 = xi**5
    xi1 = y[3][0] - y[2][0]
    xi2 = y[3][1] - y[2][1]
    # we define each column manually (also symmetric so columns = rows), it's only four by four
    col1 = (-ETA/xito3 + ETA/xito5*xi1**2 , ETA/xito5*xi1*xi2 , ETA/xito3 - ETA/xito5*xi1**2 , -ETA/xito5*xi1*xi2)
    col2 = (ETA/xito5*xi1*xi2 , -ETA/xito3 + ETA/xito5*xi2**2 , -ETA/xito5*xi1*xi2 , ETA/xito3 - ETA/xito5*xi2**2)
    col3 = (ETA/xito3 - ETA/xito5*xi1**2 , -ETA/xito5*xi1*xi2 , -ETA/xito3 + ETA/xito5*xi1**2 , ETA/xito5*xi1*xi2)
    col4 = (-ETA/xito5*xi1*xi2 , ETA/xito3 - ETA/xito5*xi2**2 , ETA/xito5*xi1*xi2 , -ETA/xito3 + ETA/xito5*xi2**2)
    return np.array((col1,col2,col3,col4))

# returns 4x4 matrix, upper right hand block of hessian
def partial_Hpp(y):
    col1 = (1/M1,0,0,0)
    col2 = (0,1/M1,0,0)
    col3 = (0,0,1/M2,0)
    col4 = (0,0,0,1/M2)
    return np.array((col1,col2,col3,col4))

def hessian_l(y):
    col1 = (0,0,0,0,0,-1,0,0)
    col2 = (0,0,0,0, 1,0,0,0)
    col3 = (0,0,0,0,0,0,0,-1)
    col4 = (0,0,0,0,0,0, 1,0)
    col5 = (0, 1,0,0,0,0,0,0)
    col6 = (-1,0,0,0,0,0,0,0)
    col7 = (0,0,0, 1,0,0,0,0)
    col8 = (0,0,-1,0,0,0,0,0)
    return np.array((col1,col2,col3,col4,col5,col6,col7,col8))

# returns 4x4x4 tensor
def partial_Hqqq(y):
    return

# takes the gradient of hamiltonian only wrt q1 and q2
def nabla_q(q):
    # assume 2bp
    # takes q returns it's gradient, which is negative the derivative of p
    r = np.array([q[0][0]-q[1][0] , q[0][1]-q[1][1]])#r from 1 to 0
    rabs = np.sqrt(normsq(r))
    nablaq = []
    nablaq.append(-r*G*M1*M2*(rabs**(-3)))# vector
    nablaq.append(r*G*M1*M2*(rabs**(-3)))
    return nablaq

# i think this one is more correct - angular momentum
def nabla_l(y):
    p1,p2,q1,q2 = y[0],y[1],y[2],y[3]
    nablal = []
    nablal.append(np.array([ -q1[1] , q1[0]])) # partial p1
    nablal.append(np.array([ -q2[1] , q2[0]]))
    nablal.append(np.array([ p1[1] , -p1[0]]))
    nablal.append(np.array([ p2[1] , -p2[0]]))
    return np.array(nablal)

# gradient of the total linear momentum in the x direction
# the level sets of this first integral are hyper-planes, so quite easy to figure out
def nabla_lin_x(y):
    return np.array([np.array([1,0]),np.array([1,0]),np.array([0,0]),np.array([0,0])])

# gradient of the total linear momentum in the y direction
def nabla_lin_y(y):
    return np.array([np.array([0,1]),np.array([0,1]),np.array([0,0]),np.array([0,0])])


r"""
Solve Poisson equation in 2D with periodic bcs in one direction
and homogeneous Neumann in the other

    \nabla^2 u = f,

Use Fourier basis for the periodic direction and Shen's Neumann basis for the
non-periodic direction.

The equation to solve is

     (\nabla^2 u, v) = (f, v)

"""
import sys
import os
import importlib
from sympy import symbols, cos, sin
import numpy as np
from shenfun import inner, div, grad, TestFunction, TrialFunction, \
    TensorProductSpace, FunctionSpace, Array, Function, comm, la

# Collect basis and solver from either Chebyshev or Legendre submodules
assert len(sys.argv) == 3, "Call with two command-line arguments"
assert sys.argv[-1].lower() in ('legendre', 'chebyshev')
assert isinstance(int(sys.argv[-2]), int)

family = sys.argv[-1].lower()
base = importlib.import_module('.'.join(('shenfun', family)))
Solver = base.la.Helmholtz

# Use sympy to compute a rhs, given an analytical solution
x, y = symbols("x,y", real=True)
ue = (1-x**3)*cos(2*y)
fe = ue-ue.diff(x, 2)-ue.diff(y, 2)

# Size of discretization
N = int(sys.argv[-2])
N = (N, N)
bc = {'left': ('N', ue.diff(x, 1).subs(x, -1)), 'right': ('N', ue.diff(x, 1).subs(x, 1))}
SN = FunctionSpace(N[0], family=family, bc=bc, mean=None)
K1 = FunctionSpace(N[1], family='F', dtype='d')
T = TensorProductSpace(comm, (SN, K1), axes=(0, 1))
u = TrialFunction(T)
v = TestFunction(T)

# Get f on quad points
fj = Array(T, buffer=fe)

# Compute right hand side of Poisson equation
f_hat = inner(v, fj)

# Get left hand side of Poisson equation
matrices = inner(v, u-div(grad(u)))

# Create Helmholtz linear algebra solver
H = Solver(*matrices)

# Solve and transform to real space
u_hat = Function(T).set_boundary_dofs()           # Solution spectral space
u_hat = H(u_hat, f_hat)       # Solve
uq = T.backward(u_hat).copy()

# Compare with analytical solution
uj = Array(T, buffer=ue)
print(abs(uj-uq).max())
assert np.allclose(uj, uq)
c = H.matvec(u_hat, Function(T))
f_hat = inner(v, fj)
assert np.allclose(c, f_hat)

if 'pytest' not in os.environ:
    import matplotlib.pyplot as plt
    plt.figure()
    X = T.local_mesh(True) # With broadcasting=True the shape of X is local_shape, even though the number of datapoints are still the same as in 1D
    plt.contourf(X[0], X[1], uq)
    plt.colorbar()

    plt.figure()
    plt.contourf(X[0], X[1], uj)
    plt.colorbar()

    plt.figure()
    plt.contourf(X[0], X[1], uq-uj)
    plt.colorbar()
    plt.title('Error')

    plt.show()


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Wed Aug  4 11:27:01 2021

@author: q

GOAL : Dev. Random Walk & LogNormal Price PDF

"""
# =============================================================================
# imports
# =============================================================================
# scientific computing
import numpy as np
# data handling
import pandas as pd
# visualization
import matplotlib.pyplot as plt

# =============================================================================
# functions
# =============================================================================

# =============================================================================
# program test
# =============================================================================

if __name__ == '__main__':

    """ Random Walk Modelling """
    def randomWalk(mu = 0, sigma = 1, periods = 252, n_paths = 1e4):
        """
        Random Walk Algorithm:
            - generate values with mu and sigma
            - cumsum each path
            - define each rows a rw period, and colums each path

        Returns :
            - pd.DataFrame :
                nrows = periods
                ncols = n_paths
                cumsum(axis = 0)
        """
        n_paths = int(n_paths)
        dt = 1 / periods
        return pd.DataFrame(np.random.normal(loc = mu * dt, scale = sigma * np.sqrt(dt), size = (periods, n_paths))).cumsum(axis = 0)

    kwargs = {'mu' : 0.06, 'sigma' : 0.4,
              'periods' : 252, 'n_paths' : 11 }

    """ Simulate Random Walks """
    df = randomWalk(**kwargs)
    # df.plot(legend = False)

    def logNormalReturnPaths(mu = 0, sigma = 1, periods = 252, n_paths = 1e4, price0 = 100):

        """
        Simulate log normal distribution of paths :

            - generate values with mu and sigma
            - cumsum each path
            - transform log returns to simple returns : use exp()

            * log returns : np.log(price1 / price0)
                - additive : use cumsum

                np.log(110 / 100)
                Out[0]: 0.09531017980432493

            * simple returns : np.exp(np.log(price1 / price0))
                - multiplicative : use cumprod

                np.exp(np.log(110 / 100))
                Out[1]: 1.1

        Returns: tuple,
                    - DataFrame with paths
                    - Terminal, pd.Series with Terminal Values for each Path

        """
        kwargs = {'mu' : mu, 'sigma' : sigma,
                 'periods' : periods, 'n_paths' : n_paths }
        df = randomWalk(**kwargs)
        paths = 100 * np.exp(df) # e^r transformation
        terminal = paths.loc[paths.index[-1]]
        return paths, terminal

    kwargs = {'mu' : 0.06, 'sigma' : 0.4,
              'periods' : 252, 'n_paths' : 1e4, 'price0' : 100 }

    paths, terminal = logNormalReturnPaths(**kwargs)

    print(f'Paths Terminal Values : mean {terminal.mean()}, std {terminal.std()}')

    # paths.loc[:, :5].plot(grid = True)
    # plt.show()
    # terminal.hist(bins = 30, grid = True)
    # plt.show()


# python3
"""Helper functions."""

import itertools
import math
import numpy as np

def to_rad(angle) -> float:
  """Convert angle (in degree) to radiants."""

  return math.pi / 180 * angle

def to_deg(rad) -> float:
  """Convert radiants to angle."""

  return rad / math.pi * 180.0

def bitprod(nbits):
  """Produce the iterable cartesian of nbits {0, 1}."""

  for bits in itertools.product([0, 1], repeat=nbits):
    yield bits

def bits2val(bits):
  """For a given enumeratable bits, compute the corresponding decimal integer."""

  # We assume bits are given in high to low order. For example,
  # the bits [1, 1, 0] will produce the value 6.
  return sum(v * (1 << (len(bits)-i-1)) for i, v in enumerate(bits))

def val2bits(val, nbits):
  """Convert decimal integer to list of {0, 1}."""

  # We return the bits in order high to low. For example,
  # the value 6 is being returned as [1, 1, 0].
  return [int(c) for c in format(val, '0{}b'.format(nbits))]

def bits2frac(bits, length):
  """For a given enumeratable bits, compute the binary fraction."""

  return sum(bits[i] * 2**(-i-1) for i in range(length))

def density_to_cartesian(rho):
  """Compute Bloch sphere coordinates from 2x2 density matrix."""

  a = rho[0, 0]
  b = rho[1, 0]
  x = 2.0 * b.real
  y = 2.0 * b.imag
  z = 2.0 * a - 1.0

  return np.real(x), np.real(y), np.real(z)

def qubit_to_bloch(psi):
  """Compute Bloch spere coordinates from 2x1 state vector/qubit."""

  return density_to_cartesian(psi.density())

def dump_bloch(x, y, z):
  """Textual output for Bloch sphere coordinates."""

  print('x: {:.2f}, y: {:.2f}, z: {:.2f}'.format(x, y, z))

def pi_fractions(val, pi='pi') -> str:
  """Convert a value in fractions of pi."""

  if val is None:
    return ''
  if val == 0:
    return '0'
  for pi_multiplier in range(1, 2):
    for frac in range(-128, 128):
      if frac and math.isclose(val, pi_multiplier * math.pi / frac):
        pi_str = ''
        if pi_multiplier != 1:
          pi_str = '{}*'.format(abs(pi_multiplier))
        if frac == -1:
          return '-{}{}'.format(pi_str, pi)
        if frac < 0:
          return '-{}{}/{}'.format(pi_str, pi, -frac)
        if frac == 1:
          return '{}{}'.format(pi_str, pi)
        return '{}{}/{}'.format(pi_str, pi, frac)

  # couldn't find fractional, just return original value.
  return f'{val}'


from functools import lru_cache
from itertools import product
from collections import namedtuple

from sympy import Symbol, Integer, poly, Eq, expand, zeros, symbols, Matrix, factorial, IndexedBase, solve, simplify

from commons import *

nature = namedtuple('nature', ['is_ordinary', 'is_exponential'])

# the following are indexed bases relative to commonly known RAs
mathcal_R, mathcal_P, mathcal_C, mathcal_S = (
    IndexedBase(r'\mathcal{R}'), # stands for the abstract RA
    IndexedBase(r'\mathcal{P}'), # stands for the Pascal triangle
    IndexedBase(r'\mathcal{C}'), # stands for the Catalan triangle
    IndexedBase(r'\mathcal{S}'), # stands for the Stirling triangle
)

gencoeff_d = IndexedBase('d') # stands for a generic coeff in a matrix

def riordan_matrix_exponential(RA):
    return lambda i,j: factorial(i)*RA(i,j)/factorial(j)

def riordan_matrix_by_convolution(dim, d, h):

    t = symbols('t')                                      # Local symbol to denote a formal variable `t`.

    with lift_to_Lambda(d, return_eq=True) as D:          # Lift equations `d` and `h` to become callables
      with lift_to_Lambda(h, return_eq=True) as H:        # objects, returning equations as well, in order
        d_eq, h_eq = D(t), H(t)                           # to let both of them depend on variable `t`.

    @lru_cache(maxsize=None)
    def column(j):                                        # Columns are memoized for the sake of efficiency.
        if not j: return d_eq                             # Base case.
        lhs = column(j-1).lhs * h_eq.lhs                  # Otherwise, use already computed column to build
        rhs = column(j-1).rhs * h_eq.rhs                  # the current `lhs` and `rhs`.
        return Eq(lhs, rhs)

    @lru_cache(maxsize=None)
    def C(j):                                             # Local function that performs Taylor expansion
        return column(j).rhs.series(t, n=dim).removeO()   # of columns, which are symbolic terms up to now.

    return lambda i, j: C(j).coeff(t, i).expand()         # Return a lambda to be plugged in a `Matrix` ctor.

def riordan_matrix_by_AZ_sequences(dim, seqs, init={(0,0):1},
                                   ctor=zeros, post=expand,
                                   lattice=None):

    if not lattice: lattice = [(n, k) for n in range(1, dim)
                                      for k in range(n+1)]

    Zseq, Aseq = seqs
    t = symbols('t')

    with lift_to_Lambda(Zseq) as Z, lift_to_Lambda(Aseq) as A:
        Z_series = Z(t).series(t, n=dim).removeO()
        A_series = A(t).series(t, n=dim).removeO()

    R = ctor(dim)

    for cell, i in init.items(): R[cell] = i

    for n, k in lattice:

        if k:
            v = sum(R[n-1, j] * A_series.coeff(t, n=i)
                    for i, j in enumerate(range(k-1, dim)))
        else:
            v = sum(R[n-1, j] * Z_series.coeff(t, n=j)
                    for j in range(dim))

        R[n, k] = v

    if callable(post): R = R.applyfunc(post)

    return lambda n, k: R[n, k]

def riordan_matrix_by_recurrence(dim, rec, init={(0,0):1},
                                 ctor=zeros, post=expand,
                                 lattice=None):

    if not lattice:
        lattice = [(n, k) for n in range(1, dim)   # `lattice` denotes the order in which coeffs in
                          for k in range(n+1)]     # the array will be computed; it can be plugged in.

    R = ctor(dim)                                  # Initial array as base for recursive construction.

    for cell, i in init.items(): R[cell] = i       # Set boundary values for the recurrence `rec`.

    for cell in lattice:                           # Visit cells as they appear in the order `lattice`;
        for comb_cell, v in rec(*cell).items():    # then, get dependencies with respect the each cell.

            try:
                comb = (1 if cell == comb_cell
                        else R[comb_cell])         # If it is possible to access the dependee cell,
                combined = v * comb                # then perform the combination using the given `v`.
            except IndexError:
                combined = 0                       # Otherwise, take `0` because combination fails.

            R[cell] += combined                    # Finally, accumulate the current combination.

    if callable(post): R = R.applyfunc(post)       # If some post processing is desired, do it.

    return lambda n, k: R[n, k]                    # Return a lambda that uses the computed `R`.

def diagonal_matrix(seq, default=0):

    def D(n, k):
        return seq[n] if n == k else default

    return D

def identity_matrix():

    def I(n, k):
        return 1 if n == k else 0

    return I

def frobenius_matrix(seq):

    m = len(seq)
    def F(n, k):
        return 1 if n+1 == k else -seq[-1-k] if n == m-1 else 0

    return F

def unit_vector(i, offset=-1):

    def U(n, k):
        return 1 if n == i+offset else 0

    return U

def Asequence(M):

    A = zeros(M.rows-1, M.cols)
    t = symbols('t')
    current_row_poly = M[0,0]

    for i in range(A.rows):

        next_row_poly = sum(M[i+1,j]*t**(i+1-j) for j in range(i+2))
        div_poly = (next_row_poly/current_row_poly).series(t, n=A.cols).removeO()

        for j in range(A.cols):
            A[i, j] = div_poly.coeff(t, n=j)

        current_row_poly = next_row_poly

    return A

def one(i):
    return 1

def columns_symmetry(M):
    return lambda i, j: M[i, i-j]

def rows_shift_matrix(by):
    return lambda i, j: 1 if i + by == j else 0

def diagonal_func_matrix(f):
    return lambda i, j: f(i) if i == j else 0

def production_matrix(M, exp=False):

    f = factorial if exp else one
    U = Matrix(M.rows, M.cols, rows_shift_matrix(by=1))
    F = Matrix(M.rows, M.cols, diagonal_func_matrix(f))
    F_inv = F**(-1)
    V = F_inv * U * F
    O = F_inv * M * F
    O_inv = O**(-1)
    PM = F * O_inv * V * O * F_inv
    PM = F_inv * PM * F if exp else PM
    PM = PM[:-1, :-1]
    return PM.applyfunc(simplify)

def inspect(M):

    P = production_matrix(M, exp=False)                    # Ordinary production matrix.
    C = production_matrix(M, exp=True)                     # "Exponential" production matrix.

    is_ord = all(P[:1-i, 1] == P[i-1:, i]                  # A RA is ordinary if columns of its PM
                 for i in range(2, P.cols))                # are shifted but equals.

    diagonals = {d: [C[j+d,j] for j in range(1,C.rows-d)]  # Fetch matrix diagonals for the
                 for d in range(C.rows-3) }                # exponential case.

    is_exp = all(map(is_arithmetic_progression,            # A Riordan array is exponential if `diagonals`
                     diagonals.values()))                  # are arithmetic progressions, all of them.

    return nature(is_ord, is_exp)

def is_arithmetic_progression(prog):

    steps = len(prog)-1
    for _ in range(steps):
        prog = [(b-a).simplify()                   # Reduce the list by consecutive differences,
                for a, b in zip(prog, prog[1:])]   # till a single object survives.

    assert len(prog) == 1                          # Consistency check of the last comment.

    return prog.pop() == 0                         # Finally, the reduced object has to vanish.

def compositional_inverse(h_eq, y=symbols('y'), check=True):

    spec, body = h_eq.lhs, h_eq.rhs                   # Destructuring function $h$ denoted by `h_eq`,
    t, = spec.args                                    # let `t` be the formal var of function $h$.
                                                      # $\bar{h}(h(t)) = t \leftrightarrow \left[ \bar{h}(y) = t\, | \, y = h(t) \right]$ allows us
    sols = solve(Eq(y, body), t)                      # to solve $y = h(t)$ with respect to $t$ because
    for sol in sols:                                  # $h(t)$ is known, denoted by `body`. For each
        L = Lambda(y, sol)                            # solution `sol`, which depends on $y$, we build
        if L(0) == 0:                                 # a callable object `L`. If it vanishes in $0$ and
                                                      # $\bar{h}(h(t))=t$, then it is a compositional
            if check: assert L(body).simplify() == t  # inverse of $h$.

            h_bar = Function(r'\bar{{ {} }}'.format(  # Prepare the name for function $\bar{h}$ and
                str(spec.func)))
            eq = Eq(h_bar(y), sol.factor())           # build the corresponding equation that defines
            return eq                                 # $\bar{h}(y)$, compositional inverse of $h(t)$.

    raise ValueError                                  # If the above code fails to return, raise an error.

def group_inverse(d_eq, h_eq, post=identity, check=True):

    t, y = symbols('t y')                                   # Formal symbols for symbolic functions $f$ and $g$.
    g_fn, f_fn = Function('g'), Function('f')

    with lift_to_Lambda(d_eq, return_eq=False) as D:        # Promote equations `d` and `h` to become
      with lift_to_Lambda(h_eq, return_eq=True) as H:       # callables objects, returning equations as well.
        f_eq = compositional_inverse(H(t), y, check)        # Let function $f$ be the compositional inverse of
        with lift_to_Lambda(f_eq, return_eq=False) as F:    # function $h$, then promote it as callable and
            F_t = F(t)                                      # (i) evaluate it at $t$;
            g = post(1/D(F_t))                              # (ii) build and refine $g$, the first function of
            f = post(F_t)                                   # the new Ra; (iii) refine $f$, the snd function.

    g_eq = Eq(g_fn(t), g.simplify())                        # Build corresponding equation objects with
    f_eq = Eq(f_fn(t), f.simplify())                        # simplified expressions.

    if check:                                               # If it is required to certify the computation,
        with lift_to_Lambda(g_eq, return_eq=False) as G:    # then promote the just built equations `g` and
          with lift_to_Lambda(f_eq, return_eq=False) as F:  # `f` to perform group operation in order to
            H_rhs = H(t).rhs                                # check that, it yields the identity element,
            assert (D(t)*G(H_rhs)).simplify() == 1          # which has (i) $1$ as first component and
            assert F(H_rhs).simplify() == t                 # (ii) $t$ as second component.

    return g_eq, f_eq


import scipy as sp
import FiniteDiff as FD

def Jacobian(func, inputs, step_size=1e-7, fdtype='c'):
    """Calculate the Jacobian of a function.

    INPUTS:
        func:       Function handle to use for Jacobian
        inputs:     Input values to function
        step_size:  Step size
        fdtype:     finite difference type ('c'entered, 'f'orward, 'b'ackward)

    RETURNS:
        jacobian:   An mxn array as specified by the tuple dim.
    """

    #test our return
    #try to find dimensions by being smart
    try:
        ndim = len(func(*inputs)), len(inputs)
    except TypeError:
        ndim = 1, len(inputs)

    jacobian = sp.zeros(ndim)

    if fdtype is 'c':
        for j in range(ndim[1]):
            jacobian[:,j] = FD.cdiff(func, inputs, vary=[j], accur=6, degree=1, tol=step_size)
    elif fdtype in ['f', 'b']:
        for j in range(ndim[1]):
            jacobian[:,j] = FD.fbdiff(func, inputs, vary=[j], accur=3, degree=1, direction=fdtype, tol=step_size)

    return jacobian

def eval_hessian(func, inputs, varyi, varyj, tol):
    #inner_pval = [x+h*tol if index in vary else x for x,index in zip(xvals, range(len(xvals)))]

    inputs = sp.asarray(inputs)
    varyi = sp.asarray(varyi)
    varyj = sp.asarray(varyj)

    f1 = func(*(inputs+(varyi+varyj)*tol))
    f2 = func(*(inputs+(varyi-varyj)*tol))
    f3 = func(*(inputs+(varyj-varyi)*tol))
    f4 = func(*(inputs-(varyi+varyj)*tol))

    test = (f1-f2-f3+f4)/(4.0*tol**2)
    return test

def Hessian(func, inputs, tol=1e-5):
    ndim = [len(inputs)]*2

    hessian = sp.zeros(ndim)

    #cache our elementary vectors
    elists = []
    for j in range(ndim[0]):
        vj=[0]*(ndim[0]-1)
        vj.insert(j,1)
        elists.append(vj)

    for i in range(ndim[0]):
        for j in range(ndim[0]):
            hessian[i,j] = eval_hessian(func, inputs, elists[i], elists[j], tol)

    return hessian


import numpy as np
from matplotlib import pyplot as plt

np.set_printoptions(precision=6)

def plotData(X, y):
    """Plots the data points X and y into a new figure

    plotData(x,y) plots the data points with + for the positive examples
    and o for the negative examples. X is assumed to be a Mx2 matrix.
    :param X: the exam scores
    :param y: the label
    :return:
    """
    positive = y == 1
    negative = y == 0
    plt.figure()
    plt.plot(X[positive, 0], X[positive, 1], 'k+', markeredgewidth=2, markersize=7)
    plt.plot(X[negative, 0], X[negative, 1], 'ko', markerfacecolor='y', markersize=7)

def sigmoid(z):
    """Compute sigmoid function

    g = sigmoid(z) computes the sigmoid of z.
    :param z:
    :return:
    """
    g = np.frompyfunc(lambda x: 1 / (1 + np.exp(-x)), 1, 1)
    return g(z).astype(z.dtype)

def costFunction(theta, X, y):
    """Compute cost and gradient for logistic regression

    J = costFunction(theta, X, y) computes the cost of using theta as the
    parameter for logistic regression and the gradient of the cost
    w.r.t. to the parameters.
    :param theta:
    :param X:
    :param y:
    :return:
    """
    # Initialize some useful values
    m = len(y)  # number of training examples

    h_theta = sigmoid(np.matmul(X, theta))
    ones = np.ones(m)
    J = -1 / m * (np.matmul(y, np.log(h_theta)) + np.matmul(ones - y, np.log(ones - h_theta)))
    grad = 1 / m * np.matmul(X.transpose(), h_theta - y)
    return J, grad

def mapFeature(X1, X2):
    """Feature mapping function to polynomial features

    mapFeature(X1, X2) maps the two input features
    to quadratic features used in the regularization exercise.
    :param X1:
    :param X2:
    :return: a new feature array with more features, comprising of
    X1, X2, X1.^2, X2.^2, X1*X2, X1*X2.^2, etc..
    """
    degree = 6
    out = np.ones(X1.shape[0])
    for i in range(1, degree + 1):
        for j in range(i + 1):
            out = np.column_stack([out, X1 ** (i - j) * X2 ** j])
    return out

def plotDecisionBoundary(theta, X, y):
    """Plots the data points X and y into a new figure with
    the decision boundary defined by theta

    plotDecisionBoundary(theta, X,y) plots the data points with + for the
    positive examples and o for the negative examples.
    :param theta:
    :param X: either
    1) Mx3 matrix, where the first column is an all-ones column for the
       intercept.
    2) MxN, N>3 matrix, where the first column is all-ones
    :param y:
    :return:
    """
    # Plot Data
    plotData(X[:, 1:], y)
    if X.shape[1] <= 3:
        # Only need 2 points to define a line, so choose two endpoints
        plot_x = np.array([min(X[:, 1]) - 2, max(X[:, 1]) + 2])

        # Calculate the decision boundary line
        plot_y = -1 / theta[2] * (theta[1] * plot_x + theta[0])

        # Plot, and adjust axes for better viewing
        plt.plot(plot_x, plot_y)

        # Legend, specific for the exercise
        plt.legend(['Admitted', 'Not admitted', 'Decision Boundary'], loc='upper right')
        plt.xlim([30, 100])
        plt.ylim([30, 100])
    else:
        # Here is the grid range
        u = np.linspace(-1, 1.5, 50)
        v = np.linspace(-1, 1.5, 50)

        z = np.zeros((len(u), len(v)))
        # Evaluate z = theta * x over the grid
        for i in range(len(u)):
            for j in range(len(v)):
                z[i, j] = np.matmul(mapFeature(u[i:i + 1], v[j:j + 1]), theta)

        u, v = np.meshgrid(u, v)
        #
        # Plot z = 0
        # Notice you need to specify the range[0, 0]
        cs = plt.contour(u, v, z.transpose(), [0], linewidth=2, colors='green')
        cs.collections[0].set_label('')

def predict(theta, X):
    """Predict whether the label is 0 or 1 using learned logistic
    regression parameters theta

    p = predict(theta, X) computes the predictions for X using a
    threshold at 0.5 (i.e., if sigmoid(theta'*x) >= 0.5, predict 1)
    :param theta:
    :param X:
    :return:
    """
    p = sigmoid(np.matmul(X, theta)) >= 0.5
    return p.astype(np.int)

def costFunctionReg(theta, X, y, lambda_):
    """Compute cost and gradient for logistic regression with regularization

    J = costFunctionReg(theta, X, y, lambda) computes the cost of using
    theta as the parameter for regularized logistic regression and the
    gradient of the cost w.r.t. to the parameters.
    :param theta:
    :param X:
    :param y:
    :param lambda_:
    :return:
    """
    # Initialize some useful values
    m = len(y)  # number of training examples
    J, grad = costFunction(theta, X, y)
    J += lambda_ / (2 * m) * np.matmul(theta[1:], theta[1:])
    grad[1:] += lambda_ / m * theta[1:]
    return J, grad


# Online Bayesian linear regression in 1d using Kalman Filter
# Based on: https://github.com/probml/pmtk3/blob/master/demos/linregOnlineDemoKalman.m

# The latent state corresponds to the current estimate of the regression weights w.
# The observation model has the form
# p(y(t) |  w(t), x(t)) = Gauss( C(t) * w(t), R(t))
# where C(t) = X(t,:) is the observation matrix for step t.
# The dynamics model has the form
# p(w(t) | w(t-1)) = Gauss(A * w(t-1), Q)
# where Q>0 allows for parameter  drift.
# We show that the result is equivalent to batch (offline) Bayesian inference.

import jax.numpy as jnp

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

from jsl.lds.kalman_filter import LDS, kalman_filter

def kf_linreg(X, y, R, mu0, Sigma0, F, Q):
    """
    Online estimation of a linear regression
    using Kalman Filters
    Parameters
    ----------
    X: array(n_obs, dimension)
        Matrix of features
    y: array(n_obs,)
        Array of observations
    Q: float
        Known variance
    mu0: array(dimension)
        Prior mean
    Sigma0: array(dimesion, dimension)
        Prior covariance matrix
    Returns
    -------
    * array(n_obs, dimension)
        Online estimation of parameters
    * array(n_obs, dimension, dimension)
        Online estimation of uncertainty
    """
    C = lambda t: X[t][None, ...]
    lds = LDS(F, C, Q, R, mu0, Sigma0)

    mu_hist, Sigma_hist, _, _ = kalman_filter(lds, y)
    return mu_hist, Sigma_hist

def posterior_lreg(X, y, R, mu0, Sigma0):
    """
    Compute mean and covariance matrix of a
    Bayesian Linear regression
    Parameters
    ----------
    X: array(n_obs, dimension)
        Matrix of features
    y: array(n_obs,)
        Array of observations
    R: float
        Known variance
    mu0: array(dimension)
        Prior mean
    Sigma0: array(dimesion, dimension)
        Prior covariance matrix
    Returns
    -------
    * array(dimension)
        Posterior mean
    * array(n_obs, dimension, dimension)
        Posterior covariance matrix
    """
    Sn_bayes_inv = inv(Sigma0) + X.T @ X / R
    Sn_bayes = inv(Sn_bayes_inv)
    mn_bayes = Sn_bayes @ (inv(Sigma0) @ mu0 + X.T @ y / R)

    return mn_bayes, Sn_bayes

def main():
    n_obs = 21
    timesteps = jnp.arange(n_obs)
    x = jnp.linspace(0, 20, n_obs)
    X = jnp.c_[jnp.ones(n_obs), x]
    F = jnp.eye(2)
    mu0 = jnp.zeros(2)
    Sigma0 = jnp.eye(2) * 10.

    Q, R = 0, 1
    # Data from original matlab example
    y = jnp.array([2.4865, -0.3033, -4.0531, -4.3359, -6.1742, -5.604, -3.5069, -2.3257, -4.6377,
                   -0.2327, -1.9858, 1.0284, -2.264, -0.4508, 1.1672, 6.6524, 4.1452, 5.2677, 6.3403, 9.6264, 14.7842])

    # Online estimation
    mu_hist, Sigma_hist = kf_linreg(X, y, R, mu0, Sigma0, F, Q)
    kf_var = Sigma_hist[-1, [0, 1], [0, 1]]
    w0_hist, w1_hist = mu_hist.T
    w0_err, w1_err = jnp.sqrt(Sigma_hist[:, [0, 1], [0, 1]].T)

    # Offline estimation
    (w0_post, w1_post), Sigma_post = posterior_lreg(X, y, R, mu0, Sigma0)
    w0_std, w1_std = jnp.sqrt(Sigma_post[[0, 1], [0, 1]])

    dict_figures = {}

    fig, ax = plt.subplots()
    ax.errorbar(timesteps, w0_hist, w0_err, fmt="-o", label="$w_0$", color="black", fillstyle="none")
    ax.errorbar(timesteps, w1_hist, w1_err, fmt="-o", label="$w_1$", color="tab:red")

    ax.axhline(y=w0_post, c="black", label="$w_0$ batch")
    ax.axhline(y=w1_post, c="tab:red", linestyle="--", label="$w_1$ batch")

    ax.fill_between(timesteps, w0_post - w0_std, w0_post + w0_std, color="black", alpha=0.4)
    ax.fill_between(timesteps, w1_post - w1_std, w1_post + w1_std, color="tab:red", alpha=0.4)

    plt.legend()
    ax.set_xlabel("time")
    ax.set_ylabel("weights")
    ax.set_ylim(-8, 4)
    ax.set_xlim(-0.5, n_obs)
    dict_figures["linreg_online_kalman"] = fig

    return dict_figures

if __name__ == "__main__":
    from jsl.demos.plot_utils import savefig
    plt.rcParams["axes.spines.right"] = False
    plt.rcParams["axes.spines.top"] = False
    dict_figures = main()
    savefig(dict_figures)
    plt.show()


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

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

def generate_offset_normal_data(D,M,K=None,count=10,sigma=0.9):
    '''Generate M class dataset with X normally distributed with eye covariance matrix with sigma^2 on diagonal
    maen(X)=0 everywhere except 1 for particular features subset fixed for each class.'''

    if K is None:
        K=int(D/M)

    X=np.zeros( (0,D) )
    Y=[]
    cov = sigma*np.eye(D)

    for m in range(M):
        mean=np.zeros(D)
        #mean=-np.ones(D)*K/(D-K)
        mean[m*K:m*K+K] = 1
        #mean[:] = m*np.random.uniform(0,1,D)
        X = np.vstack( (X, np.random.multivariate_normal(mean,cov,count) ) )
        Y+=count*[m]

    Y=np.array(Y)
    return (X,Y)


# global
import numpy as np
import ivy as _ivy
from typing import Union, Optional, Tuple, Literal
from collections import namedtuple

# local
from ivy import inf
import ivy as _ivy
from collections import namedtuple

# noinspection PyUnusedLocal,PyShadowingBuiltins
def vector_norm(x: np.ndarray,
                axis: Optional[Union[int, Tuple[int]]] = None,
                keepdims: bool = False,
                ord: Union[int, float, Literal[inf, - inf]] = 2)\
                 -> np.ndarray:

    if axis is None:
        np_normalized_vector = np.linalg.norm(x.flatten(), ord, axis, keepdims)

    else:
        np_normalized_vector = np.linalg.norm(x, ord, axis, keepdims)

    if np_normalized_vector.shape == tuple():
        return np.expand_dims(np_normalized_vector, 0)
    return np_normalized_vector

def svd(x:np.ndarray,full_matrices: bool = True) -> Union[np.ndarray, Tuple[np.ndarray,...]]:
    results=namedtuple("svd", "U S Vh")
    U, D, VT=np.linalg.svd(x, full_matrices=full_matrices)
    res=results(U, D, VT)
    return res

def diagonal(x: np.ndarray,
             offset: int = 0,
             axis1: int = -2,
             axis2: int = -1) -> np.ndarray:
    return np.diagonal(x, offset=offset, axis1=axis1, axis2=axis2)

def slogdet(x:Union[_ivy.Array,_ivy.NativeArray],full_matrices: bool = True) -> Union[_ivy.Array, Tuple[_ivy.Array,...]]:
    results = namedtuple("slogdet", "sign logabsdet")
    sign, logabsdet = np.linalg.slogdet(x)
    res = results(sign, logabsdet)
    return res


# exec(open(".//04_Numpy_Axis.py"))
print "Executing Numpy Axis"

import numpy as np

# Change False to True for this block of code to see what it does

# NumPy axis argument
if True:
    a = np.array([
        [1, 2, 3],
        [4, 5, 6],
        [7, 8, 9]
    ])

    print a.sum()
    print a.sum(axis=0)
    print a.sum(axis=1)

# Subway ridership for 5 stations on 10 different days
ridership = np.array([
    [   0,    0,    2,    5,    0],
    [1478, 3877, 3674, 2328, 2539],
    [1613, 4088, 3991, 6461, 2691],
    [1560, 3392, 3826, 4787, 2613],
    [1608, 4802, 3932, 4477, 2705],
    [1576, 3933, 3909, 4979, 2685],
    [  95,  229,  255,  496,  201],
    [   2,    0,    1,   27,    0],
    [1438, 3785, 3589, 4174, 2215],
    [1342, 4043, 4009, 4665, 3033]
])

def min_and_max_riders_per_day(ridership):
    '''
    Fill in this function. First, for each subway station, calculate the
    mean ridership per day. Then, out of all the subway stations, return the
    maximum and minimum of these values. That is, find the maximum
    mean-ridership-per-day and the minimum mean-ridership-per-day for any
    subway station.
    '''

    # Find the mean ridership per day for each subway station
    station_riders = ridership.mean(axis=0)

    # Find the maximum daily ridership and the minimum
    max_daily_ridership = station_riders.max()
    min_daily_ridership = station_riders.min()

    return (max_daily_ridership, min_daily_ridership)

import pandas as pd
weekData = pd.DataFrame({
    'temp': [70, 71, 72, 73, 74, 75, 76 ],
    'condition': ['Cloudy','Clear','Windy','Clear','Stormy','Cloudy','Clear'],
    'it_rained':[False, False, False, False, True, True, False]}, index = [
            'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'
        ])


"""
A company wants to determine the linear relationship between the selling price of their product in US dollars
 and the number of units sold in thousands.
Perform a linear regression on the following data to determine the linear predictor function
"""

from scipy.stats import linregress

x = [12, 14, 16, 18, 20]
y = [54, 57, 49, 48, 42]

slope = round(linregress(x, y).slope, 1)
intercept = round(linregress(x, y).intercept, 1)

#formula
print(f" y = {intercept} + {slope}x")


""" Compute the cost and gradeint of a given set of labeled data
"""
import numpy as np
from typing import List

from sigmoid import sigmoid

def cost_function(theta, X, y):
    """Calculates cost of current theta paremeters
    Args:
        X: input features
        y: labels
        theta: weights for input features

    Returns:
        Cost and Gradient
    """
    grad = np.zeros(theta.shape)
    num_examples = y.size

    # X => (100, 3)
    # theta => (3, 1)
    # (X * theta) => (100 x 3) * (3 x 1) => (100 x 1)
    hypothesis = sigmoid(np.dot(X, theta))
    # y => (100 x 1)
    # y.T => (1 x 100)
    # y.T * log(X * theta) => (1 x 100) x (100 x 1) => (1 x 1) scalar
    '''
    Note: It appears the np.dot will handle converting a matrix to its
    transpose if it detects that the transpose will make the operation
    succeed. Hence, we don't need the tranpose of y, but we take it
    because it's right
    '''
    J = (1/num_examples) * np.sum(
                        np.dot(-y, np.log(hypothesis)) -
                        np.dot(1-y, np.log(1 - hypothesis))
                    )
    grad = (1/num_examples) * np.dot((hypothesis - y), X)

    return J, grad


import numpy as np
import scipy.stats as stats
from UQpy.Distributions.baseclass import DistributionND

class MVNormal(DistributionND):
    """
    Multivariate normal distribution having probability density function

    .. math:: f(x) = \dfrac{1}{\sqrt{(2\pi)^k\det\Sigma}}\exp{-\dfrac{1}{2}(x-\mu)^T\Sigma^{-1}(x-\mu)}

    where :math:`\mu` is the mean vector, :math:`\Sigma` is the covariance matrix, and :math:`k` is the dimension of
    `x`.

    **Inputs:**

    * **mean** (`ndarray`):
        mean vector, `ndarray` of shape `(dimension, )`
    * **cov** (`float` or `ndarray`):
        covariance, `float` or `ndarray` of shape `(dimension, )` or `(dimension, dimension)`. Default is 1.

    The following methods are available for ``MVNormal``:

    * ``cdf``, ``pdf``, ``log_pdf``, ``rvs``, ``fit``, ``moments``.
    """
    def __init__(self, mean, cov=1.):
        if mean is not None and cov is not None:
            if len(np.array(mean).shape) != 1:
                raise ValueError('Input mean must be a 1D array.')
            if isinstance(cov, (int, float)):
                pass
            else:
                if not (len(np.array(cov).shape) in [1, 2] and all(sh == len(mean) for sh in np.array(cov).shape)):
                    raise ValueError('Input cov must be a float or ndarray of appropriate dimensions.')
        super().__init__(mean=mean, cov=cov, order_params=['mean', 'cov'])

    def cdf(self, x):
        cdf_val = stats.multivariate_normal.cdf(x=x, **self.params)
        return np.atleast_1d(cdf_val)

    def pdf(self, x):
        pdf_val = stats.multivariate_normal.pdf(x=x, **self.params)
        return np.atleast_1d(pdf_val)

    def log_pdf(self, x):
        logpdf_val = stats.multivariate_normal.logpdf(x=x, **self.params)
        return np.atleast_1d(logpdf_val)

    def rvs(self, nsamples=1, random_state=None):
        if not (isinstance(nsamples, int) and nsamples >= 1):
            raise ValueError('Input nsamples must be an integer > 0.')
        return stats.multivariate_normal.rvs(
            size=nsamples, random_state=random_state, **self.params).reshape((nsamples, -1))

    def fit(self, data):
        data = self._check_x_dimension(data)
        mle_mu, mle_cov = self.params['mean'], self.params['cov']
        if mle_mu is None:
            mle_mu = np.mean(data, axis=0)
        if mle_cov is None:
            mle_cov = np.cov(data, rowvar=False)
        return {'mean': mle_mu, 'cov': mle_cov}

    def moments(self, moments2return='mv'):
        if moments2return == 'm':
            return self.get_params()['mean']
        elif moments2return == 'v':
            return self.get_params()['cov']
        elif moments2return == 'mv':
            return self.get_params()['mean'], self.get_params()['cov']
        else:
            raise ValueError('UQpy: moments2return must be "m", "v" or "mv".')


#!/usr/bin/env python

import numpy as np

def torsion(p1, p2, p3, p4, flg_degree=False, flg_360=False):
    '''
    p1, p2, p3, p4 are numpy arrays for four coordinates by which the torsion angle phi is defined.
    '''

    v12 = p1 - p2
    v32 = p3 - p2
    v34 = p3 - p4

    m = np.cross(v12, v32)
    n = np.cross(v32, v34)

    if np.dot(v12,n) >= 0.0: # 0 < phi < 180
        #phi =   math.acos( np.dot(m,n) / math.sqrt(np.dot(m,m)*np.dot(n,n)) )
        phi =   np.arccos( np.dot(m,n) / (np.linalg.norm(m) * np.linalg.norm(n)))

    else: # -180 < phi < 0
        #phi = - math.acos( np.dot(m,n) / math.sqrt(np.dot(m,m)*np.dot(n,n)) )
        phi = - np.arccos( np.dot(m,n) / (np.linalg.norm(m) * np.linalg.norm(n)))

        if flg_360: # convert to (180 < phi < 360)
            #phi = 2 * math.pi + phi
            phi = 2 * np.pi + phi

    if flg_degree:
        #return phi * 180.0 / math.pi
        return phi * 180.0 / np.pi
    else:
        return phi

def torsion_xy(p1, p2, p3, p4):
    '''
    p1, p2, p3, p4 are numpy arrays for four coordinates by which the torsion angle phi is defined.
    '''

    v12 = p1 - p2
    v32 = p3 - p2
    v34 = p3 - p4

    m = np.cross(v12, v32)
    n = np.cross(v32, v34)

    if np.dot(v12,n) >= 0.0: # 0 < phi < 180
        phi =   math.acos( np.dot(m,n) / math.sqrt(np.dot(m,m)*np.dot(n,n)) )

    else: # -180 < phi < 0
        phi = - math.acos( np.dot(m,n) / math.sqrt(np.dot(m,m)*np.dot(n,n)) )

    return math.cos(phi), math.sin(phi)

if __name__ == "__main__":
    print('Test of torsion.py')
    print ('''
    ATOM  22440  C4'   G A   0      24.717  92.775  96.702  1.00 31.19           C
    ATOM  22458  P     A A   1      22.332  94.740  95.607  1.00 34.55           P
    ATOM  22463  C4'   A A   1      20.808  97.714  93.719  1.00 34.31           C
    ATOM  22480  P     G A   2      18.954  96.788  90.471  1.00 34.67           P
    ATOM  22485  C4'   G A   2      19.175  99.605  87.735  1.00 33.40           C
    ''')

    a = np.array([ 24.717 , 92.775 , 96.702])
    b = np.array([ 22.332 , 94.740 , 95.607])
    c = np.array([ 20.808 , 97.714 , 93.719])
    d = np.array([ 18.954 , 96.788 , 90.471])
    e = np.array([ 19.175 , 99.605 , 87.735])

    print("Torsion of C4'-P-C4'-P")
    print('  flg_360=False(default): %f rad, %f deg' % (torsion(a,b,c,d), torsion(a,b,c,d,True)))
    print('  flg_360=True          : %f rad, %f deg' % (torsion(a,b,c,d,flg_360=True), torsion(a,b,c,d,True,flg_360=True)))
    print('  cos(phi), sin(phi)    : x = %f, y = %f' % torsion_xy(a,b,c,d))

    print("Torsion of P-C4'-P-C4'")
    print('  flg_360=False(default): %f rad, %f deg' % (torsion(b,c,d,e), torsion(b,c,d,e,True)))
    print('  flg_360=True          : %f rad, %f deg' % (torsion(b,c,d,e,flg_360=True), torsion(b,c,d,e,True,flg_360=True)))
    print('  cos(phi), sin(phi)    : x = %f, y = %f' % torsion_xy(b,c,d,e))


import numpy as np
import math

class TestCode:

    def __init__(self):

        pass

    def test_the_linear_acceleration(student_answer, measured_acceleration, phi, theta):
        psi = 0.0
        g = 9.81 * np.array([[0], [0], [-1]])
        r_x = np.array([[1, 0, 0],
                        [0, np.cos(phi), -np.sin(phi)],
                        [0, np.sin(phi), np.cos(phi)]])

        r_y = np.array([[np.cos(theta), 0, np.sin(theta)],
                        [0, 1, 0],
                        [-np.sin(theta), 0, np.cos(theta)]])

        r_z = np.array([[np.cos(psi), -np.sin(psi), 0],
                        [np.sin(psi), np.cos(psi), 0],
                        [0,0,1]])

        r = np.matmul(r_z, np.matmul(r_y,r_x))

        # calculating the true acceleration in body frame by removing the gravity component
        a_body_frame = measured_acceleration - np.matmul(r, g)

        # converting the true acceleration back to the inertial frame
        a_inertial_frame = np.matmul(np.linalg.inv(r), a_body_frame)

        epsilon = 10**(-4)
        if np.all(abs(student_answer- a_inertial_frame) < np.array([[1],[1],[1]])* epsilon):
            print('Test passed')
        else:
            print('Test failed')

    def test_the_accelerometer_measurement(student_answer, acctual_a, phi, theta, sigma_a=0.0):

        psi = 0.0
        g = 9.81 * np.array([[0], [0], [-1]])
        r_x = np.array([[1, 0, 0],
                        [0, np.cos(phi), -np.sin(phi)],
                        [0, np.sin(phi), np.cos(phi)]])

        r_y = np.array([[np.cos(theta), 0, np.sin(theta)],
                        [0, 1, 0],
                        [-np.sin(theta), 0, np.cos(theta)]])

        r_z = np.array([[np.cos(psi), -np.sin(psi), 0],
                        [np.sin(psi), np.cos(psi), 0],
                        [0,0,1]])

        r = np.matmul(r_z,np.matmul(r_y,r_x))

        # Converting global frame acceleration into the body frame acceleration
        acctual_a = acctual_a.reshape(3,1)
        linear_acc_bodyframe = np.matmul(r, acctual_a)

        # Adding the gravity component
        gravity_component = np.matmul(r, g)

        # Error component
        error_component = np.random.normal(0.0, sigma_a, (3, 1))

        measured_acceleration = linear_acc_bodyframe + gravity_component + error_component

        epsilon = 10**(-3)

        if np.all(abs(student_answer- measured_acceleration) < np.array([[1],[1],[1]])* epsilon):
            print('Test passed')
        else:
            print('Test failed')

    def test_the_gyroscope_measurement(student_answer,phi, theta, phi_dot, theta_dot, sigma_omega=0.0):
        # Conversion matrix
        R =np.array([[1, np.sin(phi)*np.tan(theta)], [0, np.cos(phi)]])

        # Body rate p and q true values
        body_rate = np.matmul(np.linalg.inv(R) , np.array([[phi_dot], [theta_dot]]))

        # Adding an error to the true body rates
        measured_bodyrates = body_rate + np.random.normal(0.0, sigma_omega, (2, 1))

        epsilon = 10**(-4)

        if np.all(abs(student_answer- measured_bodyrates) < np.array([[1],[1]])* epsilon):
            print('Test passed')
        else:
            print('Test failed')

Course04/17-12_Dead Reckoning In 3D/test_three_d_object.py


import numpy as np

def normalize(v):
    """
    Normalizes 1D (possibly complex) vector
    :param v: vector to normalize
    :return: normalized vector
    """
    return v / np.sqrt(v.dot(v.conjugate()))

def gram_schmidt(B):
    """
    Gram Schmidt algorithm used to orthonormalize matrix B.
    :param B: complex matrix. e.g. \n
              B = [[b_{0,0}],[b_{0,1}],
                  [[b_{1,0}],[b_{1,1}]]\n where b_{i,j} corresponds
              to the i-th element of column basis vector j
              and the goal is to orthonormalize the basis spanned by
              the columns of B
    :return: Orthonormalized matrix with same dimensions as B
    """
    B[:, 0] = normalize(B[:, 0])
    for i in range(1, B.shape[1]):
        Ai = B[:, i]
        for j in range(0, i):
            Aj = B[:, j]
            t = Ai.dot(Aj.conjugate())
            Ai = Ai - t * Aj
        B[:, i] = normalize(Ai)
    return B

def factors(n):
    """
    Returns all factors of n
    """
    import functools
    return list(functools.reduce(list.__add__,
                                 ([i, n // i] for i in range(1, int(n ** 0.5) + 1)
                                  if n % i == 0)))