# -*- coding: utf-8 -*-
"""
Created on Sat Apr 18 13:03:24 2020

@author: Mohammad Asif Zaman

Code for testng differentiation matrix operators

Solves 𝛁²u(x,y) = g(x,y)

May 2, 20200: v1:
    - Dirichlet boundary condition implementation

May 5, 20200: v1_1:
    - Fixed a bug regarding the right-hand function
    - Figure size and font size adjusted

"""

from __future__ import print_function

import time
import math
import numpy as np
import pylab as py
import scipy.sparse as sp                 # import sparse matrix library
from scipy.sparse.linalg import spsolve

py.rcParams.update({'font.size': 20})

# import the file where the differentiation matrix operators are defined
from diff_matrices import Diff_mat_1D, Diff_mat_2D

# Defining custom plotting functions
def my_contourf(x,y,F,ttl):
    cnt = py.contourf(x,y,F,41,cmap = 'inferno')
    py.colorbar()
    py.xlabel('x'); py.ylabel('y'); py.title(ttl)
    return 0

def my_scatter(x,y,clr,ttl):
    py.plot(x,y,'.',markersize=2,color=clr)
    py.xlabel('x'); py.ylabel('y'); py.title(ttl)
    return 0

# Dirichlet boundary conditions
uL = 0.5
uR = 1.2
uT = 1.5
uB = 0

# Define independent variables
Nx = 50                         # No. of grid points along x direction
Ny = 80                         # No. of grid points along y direction
x = np.linspace(-6,6,Nx)        # x variables in 1D
y = np.linspace(-3,3,Ny)        # y variable in 1D

dx = x[1] - x[0]                # grid spacing along x direction
dy = y[1] - y[0]                # grid spacing along y direction

X,Y = np.meshgrid(x,y)          # 2D meshgrid

# 1D indexing
Xu = X.ravel()                  # Unravel 2D meshgrid to 1D array
Yu = Y.ravel()

# Source function (right hand side vector)
g = np.zeros(Nx*Ny)

# Loading finite difference matrix operators

Dx_2d, Dy_2d, D2x_2d, D2y_2d = Diff_mat_2D(Nx,Ny)   # Calling 2D matrix operators from funciton

# Boundary indices
start_time = time.time()
ind_unravel_L = np.squeeze(np.where(Xu==x[0]))          # Left boundary
ind_unravel_R = np.squeeze(np.where(Xu==x[Nx-1]))       # Right boundary
ind_unravel_B = np.squeeze(np.where(Yu==y[0]))          # Bottom boundary
ind_unravel_T = np.squeeze(np.where(Yu==y[Ny-1]))       # Top boundary

ind_boundary_unravel = np.squeeze(np.where((Xu==x[0]) | (Xu==x[Nx-1]) | (Yu==y[0]) | (Yu==y[Ny-1])))  # All boundary
ind_boundary = np.where((X==x[0]) | (X==x[Nx-1]) | (Y==y[0]) | (Y==y[Ny-1]))    # All boundary
print("Boundary search time = %1.6s" % (time.time()-start_time))

# Plot solution domain (with boundary)

py.close('all')
my_scatter(X,Y,'b','Solution grid')
my_scatter(X[ind_boundary], Y[ind_boundary],'r','Solutiohn grid with boundary')

# Construction of the system matrix
start_time = time.time()
I_sp = sp.eye(Nx*Ny).tocsr()
L_sys = D2x_2d/dx**2 + D2y_2d/dy**2     # system matrix without boundary conditions

L_sys[ind_boundary_unravel,:] = I_sp[ind_boundary_unravel,:]

# Construction of right hand vector (function of x and y)
b = g
b[ind_unravel_L] = uL
b[ind_unravel_R] = uR
b[ind_unravel_T] = uT
b[ind_unravel_B] = uB

print("System matrix and right hand vector computation time = %1.6s" % (time.time()-start_time))

# solve
start_time = time.time()
u = spsolve(L_sys,b).reshape(Ny,Nx)
print("spsolve() time = %1.6s" % (time.time()-start_time))

# Plot solution
py.figure(figsize = (14,7))
my_contourf(x,y,u,r'$\nabla^2 u = 0$')


# -*- coding: utf-8 -*-
"""
ELS 2-asset by Monte Carlo simulation

@author: Minhyun Yoo
"""
import time
import numpy as np

from math import exp, sqrt, ceil

S0_1 = 100.0; # underlying price 1
S0_2 = 100.0; # underlying price 2
T = 3.0; # maturity
r1 = 0.03; # riskless interest rate 1
r2 = 0.03; # riskless interest rate 2
discr = 0.03;
sig1 = 0.3; # volatility 1
sig2 = 0.3; # volatility 2
rho = 0.5;
ns = 10000;  # # of simulations
dateConv = 360; # 1 year
nStep = int(dateConv * T); # # of time steps

Kib = 60.0;
cpy = 0.03;
dummy = cpy*T;
face = 10000.0;
B = [90.0, 90.0, 85.0, 85.0, 80.0, 80.0]; # early redemption barrier
numExercise = len(B);
obsDate = np.array([ceil(nStep / numExercise), ceil(2.0*nStep/numExercise), ceil(3.0*nStep/numExercise),
           ceil(4.0*nStep / numExercise), ceil(5.0*nStep / numExercise), ceil(nStep)]);
payment = face*(1.0+np.array([cpy*0.5, cpy*1.0, cpy*1.5, cpy*2.0, cpy*2.5, cpy*3.0]));

# functions call
dt = T / nStep;
t0 = time.clock();
sumPayoff = 0.0;
idx = np.zeros(numExercise);

drift1 = (r1 - 0.5*sig1**2)*dt;
drift2 = (r2 - 0.5*sig2**2)*dt;
sigsqdt1 = sig1*sqrt(dt);
sigsqdt2 = sig2*sqrt(dt);

corr = [[1.0, rho],[rho, 1.0]];
M = np.matrix(np.linalg.cholesky(corr));

for i in xrange(ns):
    s1 = S0_1; s2 = S0_2;
    kievent = False; tag = False;
    cnt1 = 0; cnt2 = 0;
    payoff = 0.0; idx[:] = 0.0;

    z = M * np.matrix(np.random.normal(size = [2, nStep]));

    for j in xrange(nStep):
        s1 = s1 * exp(drift1 + sigsqdt1*z[0, j]);
        s2 = s2 * exp(drift2 + sigsqdt2*z[1, j]);

        wp = min(s1, s2);

        kievent = True if wp < Kib else kievent;

        if ((j+1) == obsDate[cnt1]):
            idx[cnt1] = wp;
            cnt1 += 1;

    for k in xrange(numExercise):
        if (idx[k] >= B[k]):
            payoff = payment[k];
            tag = True;
            cnt2 = k;
            break;

    if (tag == False):
        payoff = 100.0 * wp;
        if (kievent == False):
            if (wp >= Kib):
                payoff = face * (1.0 + dummy);
    sumPayoff += payoff * exp(-discr * obsDate[cnt2] / dateConv);

els1 = sumPayoff / ns;
t1 = time.clock();
del z;

print 'Monte Carlo Call Price : %.5f' % els1
print 'CPU time in Python(sec) : %.4f' % (t1-t0)


"""ir.py: Script that compares various Interest Rate term structure models.

A common model used in the financial industry for modelling the short rate (think overnight rate, but actually an infinitesimally short amount of time) is the Vasicek model. #
Although it is unlikely to perfectly fit the yield curve, it has some nice properties that make it a good model to work with.
The dynamics of the Vasicek model are describe below.

In this model, the parameters  are constants, and the random motion is generated by the Q measure Brownian motion .
An important property of the Vasicek model is that the interest rate is mean reverting to , and the tendency to revert is controlled by .
Also, this process is a diffusion process, hence Markovian, which will lead to some nice closed form formulas.
Finally, the future value of the interest rate is normally distributed with the distribution .

"""

__author__ = "Alexander Baker"
__copyright__ = "Copyright 2012, The Hatch Project"
__credits__ = ["Alexander Baker"]
__license__ = "GPL"
__version__ = "1.0.1"
__maintainer__ = "Alexander Baker"
__email__ = "baker.alexander@gmail.com"
__status__ = "Production"

import numpy as np
from numpy.random import standard_normal
from numpy import array, zeros, sqrt, shape

from pylab import plot, title, xlabel, ylabel, show, figure, grid

r0 = 0.5 # current UK funding rate
theta = 1.00 # 1 % long term interest rate
k = 0.3
beta = 0.03

## simulate short rate paths
n = 10000    # MC simulation trials
T = 24.    # total time
m = 100.   # subintervals
dt = T/m  # difference in time each subinterval

r = np.zeros(shape=(n, m), dtype=float) # matrix to hold short rate paths

fig1 = figure(1)
fig1.clf()
ax1a = fig1.add_subplot(121)

for j in np.arange(0,n): # number of MC simulations
	r[j,0] = r0
	for i in np.arange(1,m): #trials per simulation
		r[j,i] = r[j,i-1] + k*(theta-r[j,i-1])*dt + beta*sqrt(dt)*standard_normal();
		#print j,i, r[j,i]
        ax1a.plot(np.arange(0, T, dt), r[j])

## plot paths
t = np.arange(0, T, dt)
rT_expected = theta + (r0-theta)*pow(np.e,-k*t)
rT_stdev = sqrt( pow(beta,2)/(2*k)*(1-pow(np.e,-2*k*t)))
print 'expected', rT_expected, 'std', rT_stdev

plot(np.arange(0, T, dt), rT_expected, '-or')
plot(np.arange(0, T, dt), rT_expected+2*rT_stdev, '-ob')
plot(np.arange(0, T, dt), rT_expected-2*rT_stdev, '-ob')

print shape(t), shape(r)

title('Simulations %d Steps %d r0 %.2f alpha %.2f beta %.2f sigma %.2f' % (int(n), int(m), r0, k, theta, beta))
xlabel('steps')
ylabel('short term interest rate')
grid()

stock_ending_price = r[:,-1]
print 'average ending rate ', np.mean(stock_ending_price)

ax2a = fig1.add_subplot(122)
ax2a.hist(stock_ending_price, 100)
ax2a.grid()

show()

#rT.stdev <- sqrt( beta^2/(2*k)*(1-exp(-2*k*t)))
#matplot(t, r[,1:10], type="l", lty=1, main="Short Rate Paths", ylab="rt")
#abline(h=theta, col="red", lty=2)
#lines(t, rT.expected, lty=2)
#lines(t, rT.expected + 2*rT.stdev, lty=2)
#lines(t, rT.expected - 2*rT.stdev, lty=2)
#points(0,r0)


"""
@file:          quadraticForm.py
@description:   answers to problems in exercises 7.2
                (Linear Algebra and its applications, David C. Lay 3ed)
@author:        Hiu-kong Dan
@date:          June 20, 2021
"""

import numpy as np
from numpy import linalg
from sympy import Matrix

def common(A):
    vecs = np.linalg.eig(A)
    for vec in vecs[1]:
        print(vec / np.linalg.norm(vec))
    print(vecs[0])
    print("-"*20)

def problem15():
    A = np.array([[-2, 2, 2, 2],
                [ 2, -6, 0, 0],
                [ 2, 0, -9, 3],
                [ 2, 0, 3, -9]])
    common(A)

def problem16():
    A = np.array([[ 4, 1.5, 0, -2],
                [ 1.5, 4, 2, 0],
                [ 0, 2, 4, 1.5],
                [ -2, 0, 1.5, 4]])
    common(A)

def problem17():
    A = np.array([[ 1, 4.5, 0, -6],
                [ 4.5, 1, 6, 0],
                [ 0, 6, 1, 4.5],
                [ -6, 0, 4.5, 1]])
    common(A)

def problem18():
    A = np.array([[ 11, -6, -6, -6],
                [ -6, -1, 0, 0],
                [ -6, 0, 0, -1],
                [ -6, 0, -1, 0]])
    common(A)

if __name__ == '__main__':
    problem15()
    problem16()
    problem17()
    problem18()


"""pebbles.py

    functions used to approximate pi with the Montecarlo method.

    Circumference center is at (0,0) and has a radius of 1. The square has a side of 2 and also centered in (0,0)
"""

import random
# import math
from matplotlib import pyplot as plt
import numpy as np

# Avoid automatic display of the figures
plt.ioff()

def pointIsInside(x,y):
    """pointIsInside

    Arguments:
    x,y -- x and y coordinates of the point.

    returns true if it is inside of the Circumference.
    """
    return x**2 + y**2 <= 1.

class MontecarloApprox:
    """MontecarloApprox class

    Description: class that implements an approximation to the number
    pi using the Montecarlo method.

    Attributes of the instances:
    - self.points -- a list of the pebbles positions. Each point is a tuple in the
        (x_coordinate,y_coordinate) format
    - self.pi_values -- a list containing the value of pi after every pebble thrown
    - self.points_inside -- the number of pebbles inside of the circumference
    - self.points_total -- the total number of pebbles
    """
    def __init__(self):
        self.points = []
        self.pi_values = []
        self.points_inside = 0
        self.points_total = 0

    def __str__(self):
        return '{:.8f}'.format(self.returnBestPiValue())

    def returnBestPiValue(self):
        if self.pi_values:
            return self.pi_values[-1]
        else:
            return 0.

    def updatePi(self):
        self.pi_values.append(4 * self.points_inside / self.points_total)

    def addNewPoint(self,n=1):
        """addNewPoint

        Description: adds n points to the board.

        Arguments:
        n -- number of new pebbles (defaults to 1)
        """
        for i in range(n):
            x = 2*random.random() - 1.
            y = 2*random.random() - 1.
            self.points.append( (x,y) )
            self.points_total += 1
            if pointIsInside(x, y):
                self.points_inside += 1
            self.updatePi()

def plotTheMonteCarloExperiment(points):
    """plots the positions of the pebbles in the Montecarlo experiment

    Arguments:
    points -- the list of the points of the positions
    """

    # Create a figure
    fig,ax = plt.subplots(constrained_layout=True,figsize=(8,8))

    #
    ax.set_facecolor('lightgreen')

    # Deactivate axis ticks
    ax.tick_params(
        axis='both',       # changes apply to the x,y-axis
        which='both',      # both major and minor ticks are affected
        bottom=False,      # ticks along the bottom edge are off
        top=False,         # ticks along the top edge are off
        right = False,
        left = False,
        labelbottom=False,
        labelleft=False) # labels along the bottom edge are off

    ax.set_aspect(1.)
    ax.set_xlim(-1.01,1.01)
    ax.set_ylim(-1.01,1.01)

    rho_circle = np.linspace(0, 2 * np.pi,100)
    r_circle = np.ones(np.shape(rho_circle))

    x_circle = r_circle * np.cos(rho_circle)
    y_circle = r_circle * np.sin(rho_circle)

    ax.fill(x_circle,y_circle,facecolor='lightblue',edgecolor='blue',zorder=1,linewidth=3)

    # First the points have to be unpacked in a x and y values

    if points:
        x, y = zip(*points)
        ax.scatter(x,y,alpha=0.75,s=50.,c='black',zorder=2)

    return fig


# Exercise 4
# In a popular board game, the players roll two dice at every turn. They want to test the fairness of the dice, so
# they note the number of occurrences of each possible result, from 2 to 12. The collected data are as follows
# values      2  3  4  5  6  7  8  9 10 11 12
# occurrences 1  4  2  7 10  9  9 14  7  5  3
# 1. Find the probability mass function of the distribution
# 2. Run a chi-squared test on this data to check if it is in accordance with the discrete triangular distribution
# that characterizes a 2-dice roll: ...
# Discuss the result of the test.

# import
import numpy as np
from matplotlib import pyplot as plt
from numpy import mean, min, max, median, quantile
from scipy.stats import binom, norm, t as student, expon, poisson, chi2
from math import sqrt, pow, floor, ceil, exp

# define corrected functions for std and variance
def variance(values):
	return np.var(values, ddof=1)

def std(values):
	return np.std(values, ddof=1)

def triangular(k):
	if k >= 2 and k <= 7:
		return 1 / 36 * (k - 1)
	else:
		return 1 / 36 * (13 - k)

data = np.array([1, 4, 2, 7, 10, 9, 9, 14, 7, 5, 3])
X = range(2, 13)  # possible values
N = sum(data)  # number of trials
Y = data / N  # sample probabilities
plt.plot(X, Y, 'o--', color='k')  # bar, lines o cosa?
# plt.show()
Y = [triangular(k) for k in X]
plt.plot(X, Y, 'o--', color='r')
plt.show()

K = len(X)
T = 0
for i in range(K):
	k = X[i]
	T += (data[i] - triangular(k) * N)**2 / (N * triangular(k))

print(f"T = {T: .3f}")
print(f"Prob t>=T (p-value) = {1 - chi2.cdf(T, K-1): .4f}")


# Python program to calculate Prime numbers and subsequently Prime Factors

"""
Usage: Prime-numbers.py

Generates a sequence of Prime numbers up to the given number (n)
and also generates Prime factors for any user given number

At prompt, enter only numbers

Options
-------

-h or help		Displays this message

"""

from sys import argv, exit
import numpy as np

def prime(num):
    primeNumbers = []
    for i in np.arange(num+1):
        count_zero = 0
        if i >= 2:
            value = i
            for j in np.arange(1, value+1):
                rem = value % j
                if rem == 0:
                    count_zero = count_zero + 1
                    if count_zero >= 3:
                        break
        if count_zero == 2:
            primeNumbers.append(i)

    return primeNumbers

def factor(facNum):
    primeFactors = []
    for pN in primeNumbersArray:
        while True:
            if (facNum % pN) == 0:
                facValue = facNum / pN
                primeFactors.append(pN)
                facNum = facValue
            else:
                break

    return primeFactors

if len(argv) > 1:
    print(__doc__)
    exit(0)

while True:
    number = raw_input("Enter the number: ")
    try:
        n = int(number)
        break
    except:
        print "Error: Enter only numbers"
        continue

primeNumbers = prime(n)
print "List of Prime Numbers up to %d:" % (n)
print primeNumbers
primeNumbersArray = np.array(primeNumbers)

while True:
    pFNum = raw_input("\nNow enter any other number to obtain the Prime Factors: ")
    try:
        pFNumber = int(pFNum)
        break
    except:
        print "Error: Enter only numbers"

if pFNumber in primeNumbersArray:
    print "Its a Prime!"
else:
    primeFactors = factor(pFNumber)
    if len(primeFactors) < 2:
        print ("Your Prime Numbers list is too short to obtain the prime factors",
"Regenerate the Prime Numbers list")
    else:
        print "The Prime Factors for %d are:" %(pFNumber)
        print primeFactors


from sklearn import datasets
import numpy as np
import collections
from sklearn.naive_bayes import GaussianNB
import ml_helpers

def compute_gaussian_probability(val, mean, var):
	coeff = 1/(np.sqrt(2*np.pi) * np.sqrt(var))
	exponent = -1 * (((val - mean) ** 2) / (2 * var))
	return coeff * np.exp(exponent)

# Import the Iris flower dataset
iris = datasets.load_iris()
train_data = np.array(iris.data)
train_labels = np.array(iris.target)
num_features = train_data.data.shape[1]

# Get the class probabilities
unique_labels, class_probs = np.unique(train_labels, return_counts=True)

# Get the mean and variance of the features for ALL of the classes
mean_features, var_features = ml_helpers.compute_mean_and_var(train_data)

# Get the mean and variance of the features for EACH of the classes
class_mean_features = np.zeros((len(unique_labels), num_features))
class_var_features = np.zeros((len(unique_labels), num_features))
count = 0
for curr_label in unique_labels:
	class_data_indices = np.where(train_labels == curr_label)[0]

	temp_data = train_data[class_data_indices]
	class_mean_features[count, :], class_var_features[count, :] = ml_helpers.compute_mean_and_var(temp_data)
	count = count + 1

# ***************************************************************
# Apply the Naive Bayes Classifier MANUALLY
# ***************************************************************
predicted_classes = np.zeros(len(train_labels))
for sample_index, sample in enumerate(train_data):

	sample_probs = np.zeros(len(unique_labels))
	for curr_label_index, curr_label in enumerate(unique_labels):
		liklihood = np.prod(compute_gaussian_probability(sample, class_mean_features[curr_label_index], class_var_features[curr_label_index]))
		class_prior_prob = class_probs[curr_label_index]
		predictor_prior_prob = np.prod(compute_gaussian_probability(sample, mean_features[curr_label_index], var_features[curr_label_index]))
		sample_probs[curr_label_index] = (liklihood * class_prior_prob) / predictor_prior_prob

	predicted_classes[sample_index] = np.argmax(sample_probs)

# ***************************************************************
# Apply the Naive Bayes Classifier USING SCIKIT LEARN
# ***************************************************************
gnb = GaussianNB()
y_pred = gnb.fit(iris.data, iris.target).predict(iris.data)
print("Scikit Learn Classification Accuracy =", (iris.target == y_pred).sum()/ iris.data.shape[0])

# Compute the classification accuracy
Accuracy = 0
for label_index, curr_label in enumerate(train_labels):
	if curr_label == predicted_classes[label_index]:
		Accuracy = Accuracy + 1

Accuracy = Accuracy / len(train_labels)
print("Manual Classification Accuracy =", Accuracy)


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Mon Sep 18 19:47:01 2017

este scrip suelto es para testear el fiteo de la hiperparabola con una parabola
perfectamente conocida aun poniendole ruido

@author: sebalander
"""
# %% imports
import numpy as np
from dev import multipolyfit as mpf
import matplotlib.pyplot as plt

# %% useful funcs
def coefs2mats(coefs, n=8):
    const = coefs[0]
    jac = coefs[1:n+1]
    hes = np.zeros((n,n))
    hes[np.triu_indices(n)] = hes.T[np.triu_indices(n)] = coefs[n+1:]

    hes[np.diag_indices(n)] *= 2
    return const, jac, hes

# invento ejemplo para testear el fiteo de hiperparabola

# vert = np.random.rand(8) # considero centrado en el origen, no pierdo nada
jac = np.random.rand(8) * 2 -1
hes = np.random.rand(8,8) * 2 - 1
hes = (hes + hes.T) / 2 # lo hago simetrico

deltaX = np.random.rand(10000, 8)
#y = deltaX.dot(jac)
#y += (deltaX.reshape((-1,8,1,1))
#      * hes.reshape((1,8,8,1))
#      * deltaX.T.reshape((1,1,8,-1))).sum(axis=(1,2)).diagonal() / 2

y = np.array([jac.dot(x) + x.dot(hes).dot(x) / 2 for x in deltaX])

# %% hago el fiteo
ruidoY = np.random.randn(y.shape[0]) * 0.1

coefs, exps = mpf.multipolyfit(deltaX, y + ruidoY, 2, powers_out=True)

constRan, jacRan, hesRan = coefs2mats(coefs)

testRan = [constRan + jacRan.dot(x) + x.dot(hesRan).dot(x) / 2 for x in deltaX]

plt.figure()
plt.plot(y, testRan, 'x')
emin, emax = [np.min(y), np.max(y)]
plt.plot([emin, emax],[emin, emax])

plt.figure()
plt.plot(hes[np.tril_indices_from(hes)], hesRan[np.tril_indices_from(hesRan)], '+')

plt.figure()
plt.plot(y, y+ruidoY, 'x')

# %%

hUli = np.array([[2,-10],[-10,2]])
xx = np.random.rand(1000, 2) * 2 - 1

yy = [x.dot(hUli).dot(x) / 2 for x in xx]

coefs, exps = mpf.multipolyfit(xx, yy, 2, powers_out=True)

constRan, jacRan, hesRan = coefs2mats(coefs,n=2)


# Created by Lena
from statsmodels.tsa.ar_model import AR
from pandas.plotting import autocorrelation_plot
from statsmodels.graphics.tsaplots import plot_acf
from statsmodels.graphics.tsaplots import plot_pacf
import pandas as pd
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings('ignore')

PATH = "plots/lena/"

df = pd.read_csv("data/^GSPC.csv", index_col=0, parse_dates=True)
df.head(10)

# checking for Autocorrelation
# Autocorrelation plots
autocorrelation_plot(df)
plt.savefig(PATH + "Autocorrelation plot")
plt.show()

# Autocorrelation Function (ACF) and Partial Autocorrelation Function (PACF) plots
plot_acf(df["Adj Close"], lags=50) # lag 50 days
plt.savefig(PATH + "Autocorrelation Function plot")
plt.show()

plot_pacf(df["Adj Close"], lags=50)
plt.savefig(PATH + "Partial Autocorrelation Function plot")
plt.show()

# If the time series is stationary, the ACF/PACF plots will show a quick drop-off in correlation after a
# small amount of lag between points.
# This data is non-stationary as a high number of previous observations are correlated with future values.

### Autoregressive model ###

# train / test split
# test - predictions of last 5 years of the Adj. Close price
test_length = 1265
X = df["Adj Close"].values
train, test = X[1:len(X)-test_length], X[len(X)-test_length:]

# Fit AR model
model = AR(train)
model_fit = model.fit(maxlag=19, ic="bic")
# bic method determined best value for maxlag is 19

# make predictions for the last 5 years
train_predictions = model_fit.predict(start=19, end=len(train))
predictions = model_fit.predict(start=len(train)-1, end=len(train)+len(test)-1) # 22109 to 23374

# plot AR model train results
plt.figure(figsize = (15,10))
plt.plot(train, label = "Train Adjusted close price")
plt.plot(train_predictions, color='red', label = "AR(p) model predictions")
plt.title("Autoregressive model AR(p) - Train data")
plt.legend()
plt.savefig(PATH + "AR_Train")
plt.show()

# plot AR model prediction results
plt.figure(figsize = (15,10))
plt.plot(test, label = "Test Adjusted close price")
plt.plot(predictions, color='red', label = "AR(p) model predictions")
plt.title("Autoregressive model AR(p) - Test data")
plt.legend()
plt.savefig(PATH + "AR_Test")
plt.show()

# Train and test prediction results show that model is highly overfitted.
# The model can't generalise well and performs poorly on unseen test data - resulting in linear fit.


"""Print an input number into a series."""

from sympy import Symbol, pprint, init_printing

def print_series(n, x_value):
    """Print the series.

    x + x**2 + X**3 +... + x**n
        _       _           _
        2       3           n
    """
    init_printing(order='rev-lex')
    x = Symbol('x')
    series = x
    for i in range(2, n + 1):
        series = series + (x**i) / i
    pprint(series)

    series_value = series.subs({x:x_value})
    print('Value of the series at {0}: {1}'.format(x_value, series_value))

if __name__ == '__main__':
    n = input('Enter the number of terms you want in the series: ')
    x_value = input('Enter the value of x at which you want to evaluate the series: ')
    print_series(int(n), float(x_value))


import numpy as np
import matplotlib.pyplot as plt

x=np.array([1.0,2.0,3.0,4.0,2.0,1.0])
k = 20
y = np.zeros(20)

y[0] = x[0]
y[1] = -0.5*y[0]+x[1]

for n in range(2,k-1):
	if n < 6:
		y[n] = -0.5*y[n-1]+x[n]+x[n-2]
	elif n > 5 and n < 8:
		y[n] = -0.5*y[n-1]+x[n-2]
	else:
		y[n] = -0.5*y[n-1]
print(y)

#subplots
plt.subplot(2, 1, 1)
plt.stem(range(0,6),x)
plt.title('Digital Filter Input-Output')
plt.ylabel('$x(n)$')
plt.grid()# minor

plt.subplot(2, 1, 2)
plt.stem(range(0,k),y)
plt.xlabel('$n$')
plt.ylabel('$y(n)$')
plt.grid()# minor

plt.savefig('xnyn.png')


# Copyright 2021 Peizhi Yan. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================
from __future__ import absolute_import

import numpy as np

def sin(x):
    """sin"""
    return np.sin(x)

def d_sin(x):
    """derivative of sin"""
    return np.cos(x)

def sigmoid(x):
    """sigmoid function"""
    # sigmoid(x) = 1 / (1 + e^(-x))
    return 1. / (1. + np.e**(-x))

def d_sigmoid(x):
    """derivative of sigmoid function"""
    return sigmoid(x) * (1. - sigmoid(x))

def relu(x):
    """ReLU"""
    # relu(x) = max(0, x)
    return x * (x > 0)

def d_relu(x):
    """derivative of ReLU"""
    return 1. * (x > 0)

def linear(x):
    """linear function"""
    return x

def d_linear(x):
    """derivative of linear function"""
    return 1. * (x * 0 == 0)


#!/usr/bin/env python3
#
# Demo to show second-order collocation method for BVP
#     u'' + (1/(2+x)) u' + (11x/(2+x)) u = (-e^x (12x^3 + 7x^2 + 1))/(2+x), -1<x<1
#     u(-1) = u(1) = 0
# using various uniform mesh sizes.
#
# Daniel R. Reynolds
# SMU Mathematics
# Math 4315

# imports
import numpy
import matplotlib.pyplot as plt
from differentiation_matrix import *

### utility functions ###

def enforce_boundary(A,rhs):
    """
    Utility routine to enforce the homogeneous Dirichlet boundary conditions on
    the linear system encoded in the matrix A and right-hand side vector r.
    This routine assumes that the inputs include placeholder rows for these
    conditions.
    """
    A[0,:] = 0*A[0,:]
    A[-1,:] = 0*A[-1,:]
    A[0,0] = numpy.max(numpy.abs(numpy.diag(A)))
    A[-1,-1] = numpy.max(numpy.abs(numpy.diag(A)))
    rhs[0] = 0
    rhs[-1] = 0
    return [A, rhs]

### main script ###

# set numbers of intervals for tests
nvals = [10, 20, 40, 80, 160, 320]

# setup problem, analytical solution, etc
a = -1.0
b = 1.0
def p(x):
    return (1.0/(2+x))
def q(x):
    return (11.0*x/(2+x))
def r(x):
    return (-numpy.exp(x)*(12*x**3 + 7*x**2 + 1)/(2+x))
def utrue(x):
    return (numpy.exp(x)*(1-x**2))

# initialize plots
plt.figure(1)
x = numpy.linspace(a,b,1000)
plt.plot(x, utrue(x), label='$\hat{u}(x)$')

# initialize 'current' mesh size and error norm
h_cur = 1.0
e_cur = 1.0

# loop over partition sizes
for n in nvals:

    # get partition and differentiation matrices
    t, Dx  = differentiation_matrix(n, a, b, 2, 1)
    t, Dxx = differentiation_matrix(n, a, b, 2, 2)

    # create additional diagonal matrices
    P = numpy.diag(p(t))
    Q = numpy.diag(q(t))
    rhs = r(t)
    A, rhs = enforce_boundary(Dxx + P@Dx + Q, rhs)

    # solve linear system, compute error and h
    u = numpy.linalg.solve(A, rhs)
    e = numpy.abs(u-utrue(t))
    e_old = e_cur
    e_cur = numpy.linalg.norm(e,numpy.Inf)
    h_old = h_cur
    h_cur = numpy.max(t[1:]-t[:-1])

    # update plots
    plt.figure(1)
    plt.plot(t, u, label=('$u_{%i}(x)$' % (n)))
    plt.figure(2)
    plt.semilogy(t, e, label=('$|\hat{u}-u_{%i}|$' % (n)))

    # output current error norm and estimated convergence rate
    if (n > nvals[0]):
        print('n = %3i,  h = %.2e, ||error|| = %.2e,  conv. rate = %.2f' %
              (n, h_cur, e_cur, numpy.log(e_cur/e_old)/numpy.log(h_cur/h_old)))
    else:
        print('n = %3i,  h = %.2e, ||error|| = %.2e' % (n, h_cur, e_cur))

# finalize plots
plt.figure(1)
plt.xlabel('$x$')
plt.ylabel('$u(x)$')
plt.legend()
plt.title('Second-order FD Approximations')

plt.figure(2)
plt.xlabel('$x$')
plt.ylabel('$|\hat{u}(x) - u(x)|$')
plt.legend()
plt.title('Second-order FD Approximation Error')

plt.show()

# end of script


# This module is dedicated to summarizing single channel signal data and extracting features from it.

import numpy as np

def normalise_signal(signal):
	"""Normalise the signal to zero mean, unit variance"""
	signal_mean = np.mean(signal)
	signal_stdev = np.std(signal)
	signal_normed = [((x-signal_mean)/signal_stdev) for x in signal]
	return(signal_normed)

def mean(signal):
	""" The mean of the raw signal"""
	return(np.mean(signal))

def std_dev(signal):
	"""The standard deviation of the raw signal"""
	return(np.std(signal))

def first_differences(signal):
	"""The mean of the absolute values of the first differences of the raw signal"""
	# build the first differences list
	first_diff = []
	for i in range(0,len(signal)-1):
		first_diff.append(abs(signal[i+1]-signal[i]))

	fd_sum = sum(first_diff)
	delta = float(fd_sum)/(len(signal)-1)
	return(delta)

def norm_first_differences(signal):
	"""The mean of the absolute values of the first differences of the normalized signal"""
	signal_normed = normalise_signal(signal)
	first_diff = []
	for i in range(0,len(signal_normed)-1):
		first_diff.append(abs(signal_normed[i+1]-signal_normed[i]))

	fd_sum = sum(first_diff)
	delta = float(fd_sum)/(len(signal_normed)-1)
	return(delta)

def second_differences(signal):
	"""The mean of the absolute values of the second differences of the raw signal"""
	sec_diff = []
	for i in range(0,len(signal)-2):
		sec_diff.append(abs(signal[i+2]-signal[i]))

	fd_sum = sum(sec_diff)
	delta = float(fd_sum)/(len(signal)-2)
	return(delta)

def norm_second_differences(signal):
	"""The mean of the absolute values of the second differences of the normalized signal"""
	signal_normed = normalise_signal(signal)
	sec_diff = []
	for i in range(0,len(signal_normed)-2):
		sec_diff.append(abs(signal_normed[i+2]-signal_normed[i]))

	fd_sum = sum(sec_diff)
	delta = float(fd_sum)/(len(signal_normed)-2)
	return(delta)

def package_deal_signal(signal):
	"""Returns the package of normalised mean, stdev, normalized first and second differences"""
	normedSig = normalise_signal(signal)
	m = mean(normedSig)
	s = std_dev(normedSig)
	nfd = norm_first_differences(signal)
	nsd = norm_second_differences(signal)

	return m,s,nfd,nsd

def package_deal_signal_mm(signal):
	"""Returns the package of normalised mean, stdev, normalized first and second differences"""
	normedSig = normalise_signal(signal)
	m = mean(normedSig)
	s = std_dev(normedSig)
	mini = min(normedSig)
	maxi = max(normedSig)
	nfd = norm_first_differences(signal)
	nsd = norm_second_differences(signal)

	return m,s,nfd,nsd, mini, maxi

def data_binarizer(ratings, threshold):
	"""binarizes the data below and above the threshold"""
	binarized = []
	for rating in ratings:
		if rating <= threshold:
			binarized.append(0)
		else:
			binarized.append(1)
	return binarized


"""
A small collection of well-known functions for testing or benchmarking
"""
import numpy as np
import torch as to

import pyrado

def rosenbrock(x: [to.Tensor, np.ndarray]) -> (to.Tensor, np.ndarray):
    """
    The Rosenbrock function
    (consistent with https://docs.scipy.org/doc/scipy/reference/tutorial/optimize.html)
    :param x: multi-dim column vector, or array thereof
    :return: value of the rosenbrock function at the input point, or array thereof
    """
    if isinstance(x, to.Tensor):
        return to.sum(100.*to.pow(x[1:] - to.pow(x[:-1], 2), 2) + to.pow((1. - x[:-1]), 2), dim=0)
    elif isinstance(x, np.ndarray):
        return np.sum(100.*np.power(x[1:] - np.power(x[:-1], 2), 2) + np.power((1. - x[:-1]), 2), axis=0)
    else:
        raise pyrado.TypeErr(given=x, expected_type=[np.ndarray, to.Tensor])

def noisy_nonlin_fcn(x: [to.Tensor, np.ndarray], f: float = 1., noise_std: float = 0.) -> [to.Tensor, np.ndarray]:
    """
    A 1-dim function (sinus superposed with polynomial), representing the black box function in Bayesian optimization

    :param x: function argument
    :param noise_std: scale of the additive noise sampled from a standard normal distribution
    :param f: frequency of the sinus wave [Hz]
    :return: function value
    """
    if isinstance(x, to.Tensor):
        return -to.sin(2*np.pi*f*x) - to.pow(x, 2) + 0.7*x + noise_std*to.randn_like(x)
    elif isinstance(x, np.ndarray):
        return -np.sin(2*np.pi*f*x) - np.power(x, 2) + 0.7*x + noise_std*np.random.randn(*x.shape)
    else:
        raise pyrado.TypeErr(given=x, expected_type=[np.ndarray, to.Tensor])


# Function for the Method of least squares
# by Justinas Smertinas
# Edited by Ali Rassolie
# Edited again by Justinas Smertinas

#What to import from numpy.
from numpy import array, transpose, dot, linalg, power

#We want to find the best fitting polynomial of any order (that you choose)
#between a set of point in the XY plane.
#For this we employ a Method of Least Squares.
#The following function returns a list of coefficients for a polynomial
#of order chosen by the user.
#Exanple of the return [a, b, c, d] where a is coefficient of the largest
#degree term (in this case 3).

#This will give you whatever order polynomial you want, babe.
class Algo:
    def __init__(self):
        pass

    def leastSquares(self, x=None, y=None, order=1):
        #We note the length of the input list so that we do not have to compute it again
        lengthOfList = len(x)
        #We set up 3 list that later will be turned into numpy
        # A transposed

        At = []

        #We create A transposed list by appending list of X raised
        #to powers of descending order.
        for i in reversed(range(order+1)):
            At.append(power(x, i))
        #We turn At into a numpy array
        #And create its transversed version.
        At = array(At)
        A = At.transpose()

        #We solve a systen <At*A>=<At*Y>
        solutionArray = linalg.solve(dot(At, A), dot(At, y))
        #However we obtain solution in form of an Array and since I dislike it's format
        #I turn it into a simple list with the folowing for loop.
        solution = []
        for i in range(len(solutionArray)):
            solution.append(solutionArray[i])
        return solution

    #Returns a list of Y approximations from known X and Y for wanted x.
    #We need a list of known X and Y values to find polynomial approximations
    #and we also need a list of X values, for which we want approximated values.
    def leastSquaresApproximationResults(self, xKnown = None, xWanted = None, yKnown=None, order = 1):
        #We calculate the polynomial coefficients
        coefficients = self.leastSquares(xKnown, yKnown, order)
        #We reverse the list for later convenience when calculating approximated Y values
        coefficients.reverse()
        #We create a list that we will alter return
        yApproxList = []
        #We iterate through the list of wanted X Values
        for i in xWanted:
            #We calculate approximation of Y values for wanted X and append it to the list
            yApprox = 0
            for j in range(len(coefficients)):
                yApprox += coefficients[j]*(i**j)
            yApproxList.append(yApprox)
        #We return the list of approximated Y values
        return yApproxList


#!/usr/bin/env python3
#
# Script to compare polynomial interpolants using various choices of node types.
#
# Daniel R. Reynolds
# SMU Mathematics
# Math 4315

# imports
import numpy
import matplotlib.pyplot as plt
from Lagrange import Lagrange

# set numbers of nodes for tests
nvals = [5, 10, 20, 40]

# set function and interval that we will interpolate
def f(x):
    return 1/(1+x**2)
a = -5
b = 5

# set evaluation points to compare interpolants
x = numpy.linspace(a, b, 2001)

# initialize plots
plt.figure(1)    # uniform nodes
plt.plot(x, f(x), label='$f(x)$')
plt.figure(3)    # random nodes
plt.plot(x, f(x), label='$f(x)$')
plt.figure(5)    # Chebyshev nodes of first kind
plt.plot(x, f(x), label='$f(x)$')
plt.figure(7)    # Chebyshev nodes of second kind
plt.plot(x, f(x), label='$f(x)$')

# loop over node numbers
for n in nvals:

   print("Testing with n =", n)

   # uniformly-spaced nodes
   plt.figure(1)
   t = numpy.linspace(a,b,n+1)
   p = Lagrange(t, f(t), x)
   e = numpy.abs(f(x)-p)
   plt.plot(x, p, label=('$p_{%i}(x)$, error = %.2e' % (n,numpy.linalg.norm(e,numpy.inf))))
   plt.figure(2)
   plt.semilogy(x, e, label=('$|f-p_{%i}|$' % (n)))

   # random nodes
   plt.figure(3)
   t = a + (b-a)*numpy.random.rand(n+1)
   p = Lagrange(t, f(t), x)
   e = numpy.abs(f(x)-p)
   plt.plot(x, p, label=('$p_{%i}(x)$, error = %.2e' % (n,numpy.linalg.norm(e,numpy.inf))))
   plt.figure(4)
   plt.semilogy(x, e, label=('$|f-p_{%i}|$' % (n)))

   # Chebyshev nodes of the first kind
   plt.figure(5)
   t = (a+b)/2 + (b-a)/2*numpy.cos((2*numpy.linspace(0,n,n+1)+1)/(2*n+2)*numpy.pi)
   p = Lagrange(t, f(t), x)
   e = numpy.abs(f(x)-p)
   plt.plot(x, p, label=('$p_{%i}(x)$, error = %.2e' % (n,numpy.linalg.norm(e,numpy.inf))))
   plt.figure(6)
   plt.semilogy(x, e, label=('$|f-p_{%i}|$' % (n)))

   # Chebyshev nodes of the second kind
   plt.figure(7)
   t = (a+b)/2 - (b-a)/2*numpy.cos(numpy.linspace(0,n,n+1)*numpy.pi/n)
   p = Lagrange(t, f(t), x)
   e = numpy.abs(f(x)-p)
   plt.plot(x, p, label=('$p_{%i}(x)$, error = %.2e' % (n,numpy.linalg.norm(e,numpy.inf))))
   plt.figure(8)
   plt.semilogy(x, e, label=('$|f-p_{%i}|$' % (n)))

# finalize plots
plt.figure(1)
plt.xlabel('$x$')
plt.ylabel('$f(x)$, $p(x)$')
plt.legend()
plt.title('Uniformly-spaced nodes')

plt.figure(2)
plt.xlabel('$x$')
plt.ylabel('$|f(x) - p(x)|$')
plt.legend()
plt.title('Uniformly-spaced node error')

plt.figure(3)
plt.xlabel('$x$')
plt.ylabel('$f(x)$, $p(x)$')
plt.legend()
plt.title('Random nodes')

plt.figure(4)
plt.xlabel('$x$')
plt.ylabel('$|f(x) - p(x)|$')
plt.legend()
plt.title('Random node error')

plt.figure(5)
plt.xlabel('$x$')
plt.ylabel('$f(x)$, $p(x)$')
plt.legend()
plt.title('Chebyshev nodes of first kind')

plt.figure(6)
plt.xlabel('$x$')
plt.ylabel('$|f(x) - p(x)|$')
plt.legend()
plt.title('Chebyshev node of first kind error')

plt.figure(7)
plt.xlabel('$x$')
plt.ylabel('$f(x)$, $p(x)$')
plt.legend()
plt.title('Chebyshev nodes of second kind')

plt.figure(8)
plt.xlabel('$x$')
plt.ylabel('$|f(x) - p(x)|$')
plt.legend()
plt.title('Chebyshev node of second kind error')

plt.show()

# end of script


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Mon Jan 27 13:20:01 2020

@author: Oscar
"""
import numpy as np

def straighLine(x, m, n):
    y = m * x + n
    return y

def polFunc(x, a, b, c, d):
    y = (a * x**3) + (b * x**2) + c * x + d
    return y

def sinFunc(x, m, n, a, w, ph):
    y = m * x + a * (np.sin(w * x + ph)) + n
    return y

def genData(typeData,X,slope,axisY,a,b,c,d,amplitude,angular,phase):
    func = {
        'straighLine': straighLine(X, slope, axisY),
        'polinomial': polFunc(X, a, b, c, d),
        'senoidal': sinFunc(X, slope, axisY, amplitude, angular, phase)
    }
    return func[typeData]


# -*- coding: utf-8 -*-
"""golden section search

This module provides a Numba JIT compilled golden section search optimizer for a custom objective.
"""

import math
import numpy as np
from numba import njit

@njit
def optimizer(obj,a,b,args=(),tol=1e-6):
    """ golden section search optimizer

    Args:

        obj (callable): 1d function to optimize over
        a (double): minimum of starting bracket
        b (double): maximum of starting bracket
        args (tuple): additional arguments to the objective function
        tol (double,optional): tolerance

    Returns:

        (float): optimization result

    """

    inv_phi = (np.sqrt(5) - 1) / 2 # 1/phi
    inv_phi_sq = (3 - np.sqrt(5)) / 2 # 1/phi^2

    # a. distance
    dist = b - a
    if dist <= tol:
        return (a+b)/2

    # b. number of iterations
    n = int(np.ceil(np.log(tol/dist)/np.log(inv_phi)))

    # c. potential new mid-points
    c = a + inv_phi_sq * dist
    d = a + inv_phi * dist
    yc = obj(c,*args)
    yd = obj(d,*args)

    # d. loop
    for _ in range(n-1):
        if yc < yd:
            b = d
            d = c
            yd = yc
            dist = inv_phi*dist
            c = a + inv_phi_sq * dist
            yc = obj(c,*args)
        else:
            a = c
            c = d
            yc = yd
            dist = inv_phi*dist
            d = a + inv_phi * dist
            yd = obj(d,*args)

    # e. return
    if yc < yd:
        return (a+d)/2
    else:
        return (c+b)/2


from pylab import *
from scipy import stats

K = 10
N = 10000
# Each arm is a Beta distribution
mu = linspace(0.1, 0.9, K)
alpha = ones(N)
beta = (1 - mu) / mu

def pull_arm(i):
	return stats.beta(alpha[i], beta[i]).rvs()

def epsilon_greedy(epsilon):
	mu_h = zeros(K) 	# Empirical mean
	n = zeros(K)		# Number of times an arm is pulled
	G = zeros(N)		# Gain at round i
	II = zeros(N)		# Choice of arm at round i
	for i in xrange(N):
		I = argmax(mu_h)
		# Explore a new arm with probability epsilon
		if rand() < epsilon:
			a = arange(K)
			a[I], a[-1] = a[-1], a[I]
			I = a[:-1][randint(0, K-1)]
		g = pull_arm(I)
		G[i] = g
		II[i] = I
		# Update empirical mean
		mu_h[I] = (mu_h[I] * n[I] + g) / (n[I] + 1)
		n[I] += 1
	return G, II

def UCB1():
	mu_h = zeros(K) 	# Empirical mean
	ucb = ones(K)		# Upper Confidence Bounds
	n = zeros(K)		# Number of times an arm is pulled
	G = zeros(N)		# Gain at round i
	II = zeros(N)		# Choice of arm at round i
	for i in xrange(N):
		# Pull the arm with the highest bound
		I = argmax(ucb)
		g = pull_arm(I)
		G[i] = g
		II[i] = I
		# Update the bound
		n[I] += 1
		mu_h[I] = (mu_h[I] * n[I] + g) / (n[I] + 1)
		ucb[I] = mu_h[I] + sqrt((2*log(i+1)) / n[I])
	return G, II

def thompson_sampling():
	mu_h = zeros(K) 	# Empirical mean
	ucb = ones(K)		# Upper Confidence Bounds
	n = zeros(K)		# Number of times an arm is pulled
	S = zeros(K)		# Number of success
	F = zeros(K)		# Number of failure
	G = zeros(N)		# Gain at round i
	II = zeros(N)		# Choice of arm at round i
	for i in xrange(N):
		theta = zeros(K)
		for j in xrange(K):
			theta[j] = stats.beta(S[j]+1, F[j]+1).rvs()
		I = argmax(theta)
		g = pull_arm(I)
		G[i] = g
		II[i] = I
		# Update the posterior using a Benourlli trial
		if rand() < g:
			S[I] += 1
		else:
			F[I] += 1
	return G, II

def exp3(gamma):
	w = ones(K) 		# Arm weights
	n = zeros(K)		# Number of times an arm is pulled
	G = zeros(N)		# Gain at round i
	II = zeros(N)		# Choice of arm at round i
	for i in xrange(N):
		# Pull the arm with highest P
		p = (1 - gamma) * w / sum(w) + gamma / K
		I = choice(K, p=p)
		g = pull_arm(I)
		G[i] = g
		II[i] = I
		# Update the weight
		w[I] = w[I] * exp(gamma * g / p[I] / K)
	return G, II

def random_bandit():
	n = zeros(K)		# Number of times an arm is pulled
	G = zeros(N)		# Gain at round i
	II = zeros(N)		# Choice of arm at round i
	for i in xrange(N):
		# Pull the arm with highest P
		I = randint(0, K)
		g = pull_arm(I)
		G[i] = g
		II[i] = I
	return G, II

def main():
	figure()
	title('Average Gain Overtime')
	# e-greedy
	for e in [0.05, 0.1]:
		G, II = epsilon_greedy(e)
		# Could also add plot of % of optimal actions
		plot(cumsum(G) / arange(1, N+1), label='EG w/ e = %.3f'%(e))
	# UCB
	G, II = UCB1()
	plot(cumsum(G) / arange(1, N+1), label='UCB1')
	# Thompson sampling
	G, II = thompson_sampling()
	plot(cumsum(G) / arange(1, N+1), label='TS')
	# Exp3
	for gamma in [0.2]:
		G, II = exp3(gamma)
		plot(cumsum(G) / arange(1, N+1), label='EXP3 w/ r = %.3f'%(gamma))
	# Random bandit
	G, II = random_bandit()
	plot(cumsum(G) / arange(1, N+1), '--', label='Random')
	legend()
	xlabel('Round')
	ylabel('Gain')
	show()

if __name__ == '__main__':
	main()


# -*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets # load iris dataset

class LogisticRegression:

    def __init__(self, learning_rate=0.01, epochs=200):
        self.learning_rate = learning_rate
        self.epochs = epochs

    def sigmoid(self, z):
        """
        Compute value of sigmoid function "g", where:
        g(z) = 1 / (1 + e^-z)
        """
        g = 1 / (1 + np.exp(-z))
        return g

    def hypothesis(self, X, theta):
        """
       Compute hypothesis "h" where: h(x) = g(z) with:
            z = X.T * theta
            g, a sigmoid function

		Parameters
    	------------
    	X: numpy array
			Features vector.
    	theta: numpy array
			Parameters vector.

		Returns
    	------------
		numpy ndarray
		"""
        z = X.dot(theta)
        h = self.sigmoid(z)
        return h

    def compute_cost(self, h, y):
        """
		Compute value of cost function "J", where:
		J(theta) = -np.average(y * np.log(h) + (1 - y) * np.log(1 - h))

		Parameters
    	------------
    	h: numpy array
			Predictions vector.
		y: numpy array
			Target vector.

		Returns
    	------------
		Value of cost function J
		"""
        m = len(y)
        J = -(1/m) * np.sum(y * np.log(h) + (1 - y) * np.log(1 - h))
        return J

    def add_intercept(self, X):
        """
        Add intercept to feature vector.
        """
        return np.c_[np.ones((m, 1)), X]

    def fit(self, X, y):
        """
		Fit theta to the training set.

		Parameters
    	------------
    	epochs: int
			Number of iterations.
    	learning_rate: float
			Rate at which theta is updated

		Returns
    	------------
		numpy ndarray
		"""
        X_b = self.add_intercept(X)
        costs = []
        self.theta = np.random.rand(X_b.shape[1])
        for epoch in range(self.epochs):
            h = self.hypothesis(X_b, self.theta)
            error = h - y
            gradients = 1/m * X_b.T.dot((error))
            self.theta = self.theta - self.learning_rate * gradients
            cost = self.compute_cost(h, y)
            costs.append(cost)

        self.costs = costs
        self.epochs = epochs

        return self.theta

    def predict(self, X):
        """
        """
        X_b = self.add_intercept(X)
        self.predictions = self.hypothesis(X_b, self.theta)
        return self.predictions

    def plot_cost(self):
        """Plot iterations versus cost function.

        Returns
        -----------
        matploblib figure
        """
        plt.figure()
        plt.plot(np.arange(1, self.epochs+1), self.costs)
        plt.xlabel("Iterations")
        plt.ylabel("Cost")
        plt.title("Cost function minimization")
        plt.show()

    def plot_model(self, X, y):
        """Plot fitted model.

        Returns
        -----------
        matploblib figure
        """
        plt.figure()
        x_values = [np.min(x[:, 0]), np.max(x[:, 1] + 3)]
        y_values = -(self.theta[0] + np.dot(self.theta[1], x_values)) / self.theta[2]
        plt.scatter(x[:,0], x[:,1], c=y)
        plt.plot(x_values, y_values, label='Decision Boundary')
        plt.title("Fitted model")
        plt.show()

if __name__ == "__main__":
    iris = datasets.load_iris()
    x = iris.data[:, :2] # select only the first 2 features
    y = (iris.target != 0) * 1 # make dataset into binary classification problem
    model = LogisticRegression(learning_rate=0.1, epochs=1000)
    model.fit(x, y)

    print("theta_hat", model.theta)

    model.plot_cost()
    model.plot_model(x, y)


"""
Implementation of SVM using cvxopt package. Implementation uses
soft margin and I've defined linear, polynomial and gaussian kernels.

To understand the theory (which is a bit challenging) I recommend reading the following:
http://cs229.stanford.edu/notes/cs229-notes3.pdf
https://www.youtube.com/playlist?list=PLoROMvodv4rMiGQp3WXShtMGgzqpfVfbU (Lectures 6,7 by Andrew Ng)

To understand how to reformulate the optimization problem we obtain
to get the input to cvxopt QP solver this blogpost can be useful:
https://xavierbourretsicotte.github.io/SVM_implementation.html

Programmed by Aladdin Persson <aladdin.persson at hotmail dot com>
*    2020-04-26 Initial coding

"""

import numpy as np
import cvxopt
from utils import create_dataset, plot_contour

def linear(x, z):
    return np.dot(x, z.T)

def polynomial(x, z, p=5):
    return (1 + np.dot(x, z.T)) ** p

def gaussian(x, z, sigma=0.1):
    return np.exp(-np.linalg.norm(x - z, axis=1) ** 2 / (2 * (sigma ** 2)))

class SVM:
    def __init__(self, kernel=gaussian, C=1):
        self.kernel = kernel
        self.C = C

    def fit(self, X, y):
        self.y = y
        self.X = X
        m, n = X.shape

        # Calculate Kernel
        self.K = np.zeros((m, m))
        for i in range(m):
            self.K[i, :] = self.kernel(X[i, np.newaxis], self.X)

        # Solve with cvxopt final QP needs to be reformulated
        # to match the input form for cvxopt.solvers.qp
        P = cvxopt.matrix(np.outer(y, y) * self.K)
        q = cvxopt.matrix(-np.ones((m, 1)))
        G = cvxopt.matrix(np.vstack((np.eye(m) * -1, np.eye(m))))
        h = cvxopt.matrix(np.hstack((np.zeros(m), np.ones(m) * self.C)))
        A = cvxopt.matrix(y, (1, m), "d")
        b = cvxopt.matrix(np.zeros(1))
        cvxopt.solvers.options["show_progress"] = False
        sol = cvxopt.solvers.qp(P, q, G, h, A, b)
        self.alphas = np.array(sol["x"])

    def predict(self, X):
        y_predict = np.zeros((X.shape[0]))
        sv = self.get_parameters(self.alphas)

        for i in range(X.shape[0]):
            y_predict[i] = np.sum(
                self.alphas[sv]
                * self.y[sv, np.newaxis]
                * self.kernel(X[i], self.X[sv])[:, np.newaxis]
            )

        return np.sign(y_predict + self.b)

    def get_parameters(self, alphas):
        threshold = 1e-5

        sv = ((alphas > threshold) * (alphas < self.C)).flatten()
        self.w = np.dot(X[sv].T, alphas[sv] * self.y[sv, np.newaxis])
        self.b = np.mean(
            self.y[sv, np.newaxis]
            - self.alphas[sv] * self.y[sv, np.newaxis] * self.K[sv, sv][:, np.newaxis]
        )
        return sv

if __name__ == "__main__":
    np.random.seed(1)
    X, y = create_dataset(N=50)

    svm = SVM(kernel=gaussian)
    svm.fit(X, y)
    y_pred = svm.predict(X)
    plot_contour(X, y, svm)

    print(f"Accuracy: {sum(y==y_pred)/y.shape[0]}")


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

class Bezier:
    """
    Bezier curve interpolation around points

        Attributes:
            n: The number of points around which it will be interpolated
            points: The coordinate of the points around which it will be interpolated
            curve_pts_num: The number of points on a Bezier curve between two points
    """
    n = None
    points = None
    curve_pts_num = None
    curve_pts = None
    C = None
    P = None
    A = None
    B = None

    def __init__(self, points, curve_pts_num = 30):
        """
        Initializes the class

            Parameters:
                points: The coordinate of the points around which it will be interpolated
                curve_pts_num: The number of points on a Bezier curve between two points
        """
        self.n = len(points)
        self.points = points
        self.curve_pts_num = curve_pts_num
        self.fixVariables()

    def fixVariables(self):
        """
        Fixes the type of the variables
        """
        if type(self.points) != np.ndarray:
            self.points = np.array(self.points)

    def createCoefficientMatrix(self):
        """
            Creates the coefficient matrix for the Bezier curve interpolation
        """
        C = np.zeros((self.n, self.n))

        for i in range(self.n):
            r = i + 1 if i + 1 < self.n else (i + 1) % self.n
            row = np.zeros(self.n)
            row[i], row[r] = 1, 2
            C[i] = row

        self.C = C

    def createEndPointVector(self):
        """
        Creates the column vector which contains the end points of each curve connecting two points
        """
        P = np.zeros((self.n, 2))

        for i in range(self.n):
            l = i + 1 if i + 1 < self.n else (i + 1) % self.n
            r = i + 2 if i + 2 < self.n else (i + 2) % self.n

            val = 2 * self.points[l] + self.points[r]
            P[i] = val

        self.P = P

    def findControlPoints(self):
        """
        Find the control points for the Bezier curve
        """
        A = np.linalg.solve(self.C, self.P)
        B = np.zeros_like(A)

        for i in range(self.n):
            l = i + 1 if i + 1 < self.n else (i + 1) % self.n
            B[i] = 2 * self.points[l] - A[l]

        self.A = A
        self.B = B

    def findPoints(self):
        """
        Finds the points on the smooth curve
        """
        self.createCoefficientMatrix()
        self.createEndPointVector()
        self.findControlPoints()

        all_pts = []

        for i in range(self.n):
            next_i = i + 1 if i + 1 < self.n else (i + 1) % self.n
            dpts = np.linspace(0, 1, self.curve_pts_num)
            for j in dpts:
                pt = np.power(1 - j, 3) * self.points[i] + 3 * j * np.power(1 - j, 2) * self.A[i] + 3 * (1 - j) * np.power(j, 2) * self.B[i] + np.power(j, 3) * self.points[next_i]
                all_pts.append(pt.tolist())

        self.curve_pts = np.array(all_pts)

    def getPoints(self):
        """
        Return the points on the curve. If they haven't been computed, compute them
        """
        if self.curve_pts == None:
            self.findPoints()

        return self.curve_pts

    def draw(self):
        """
        Draws a plot of the curve and the points
        """
        x, y = self.curve_pts[:,0], self.curve_pts[:,1]
        px, py = self.points[:,0], self.points[:,1]
        plt.plot(x, y, "b-")
        plt.plot(px, py, "ko")
        plt.axes().set_aspect('equal')
        plt.show()


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

# theta''(t) + b*theta'(t) + c*sin(theta(t)) = 0
# theta'(t) = omega(t)
# omega'(t) = -b*omega(t) - c*sin(theta(t))

def pend(y, t, b, c):
    theta, omega = y
    dydt = [omega, -b*omega - c*np.sin(theta)]
    return dydt

b = 0.25
c = 5.0

y0 = [np.pi - 0.1, 0.0]

t = np.linspace(0, 10, 101)

sol = odeint(pend, y0, t, args=(b, c))

plt.plot(t, sol[:, 0], 'b', label='theta(t)')
plt.plot(t, sol[:, 1], 'g', label='omega(t)')
plt.legend(loc='best')
plt.xlabel('t')
plt.grid()
plt.show()


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

# # Scenario Analysis: Pop Up Shop
#
# ![](https://upload.wikimedia.org/wikipedia/commons/thumb/c/c5/Weich_Couture_Alpaca%2C_D%C3%BCsseldorf%2C_December_2020_%2809%29.jpg/300px-Weich_Couture_Alpaca%2C_D%C3%BCsseldorf%2C_December_2020_%2809%29.jpg)
#
# Kürschner (talk) 17:51, 1 December 2020 (UTC), CC0, via Wikimedia Commons

# In[1]:

# install Pyomo and solvers for Google Colab
import sys
if "google.colab" in sys.modules:
    get_ipython().system('wget -N -q https://raw.githubusercontent.com/jckantor/MO-book/main/tools/install_on_colab.py ')
    get_ipython().run_line_magic('run', 'install_on_colab.py')

# ## The problem
#
# There is an opportunity to operate a pop-up shop to sell a unique commemorative item for events held at a famous location. The items cost 12 € each and will selL for 40 €. Unsold items can be returned to the supplier at a value of only 2 € due to their commemorative nature.
#
# | Parameter | Symbol | Value |
# | :---: | :---: | :---: |
# | sales price | $r$ | 40 € |
# | unit cost | $c$ | 12 € |
# | salvage value | $w$ | 2 € |
#
# Profit will increase with sales. Demand for these items, however, will be high only if the weather is good. Historical data suggests the following scenarios.

# | Scenario ($s$) | Demand ($d_s$) | Probability ($p_s$) |
# | :---: | :-----: | :----------: |
# | Sunny Skies | 650 | 0.10 |
# | Good Weather | 400 | 0.60 |
# | Poor Weather | 200 | 0.30 |
#
# The problem is to determine how many items to order for the pop-up shop.
#
# The dilemma is that the weather won't be known until after the order is placed. Ordering enough items to meet demand for a good weather day results in a  financial penalty on returned goods if the weather is poor. But ordering just enough items to satisfy demand on a poor weather day leaves "money on the table" if the weather is good.
#
# How many items should be ordered for sale?

# ## Expected value for the mean scenario (EVM)
#
# A naive solution to this problem is to place an order equal to the expected demand. The expected demand is given by
#
# $$
# \begin{align*}
# \mathbb E[D] & = \sum_{s\in S} p_s d_s
# \end{align*}
# $$
#
# Choosing an order size $x = \mathbb E[d]$ results in an expected profit we call the **expected value of the mean scenario (EVM)**.
#
# Variable $y_s$ is the actual number of items sold if scenario $s$ should occur. The number sold is the lesser of the demand $d_s$ and the order size $x$.
#
# $$
# \begin{align*}
# y_s & = \min(d_s, x) & \forall s \in S
# \end{align*}
# $$
#
# Any unsold inventory $x - y_s$ remaining after the event will be sold at the salvage price $w$. Taking into account the revenue from sales $r y_s$, the salvage value of the unsold inventory $w(x - y_s)$, and the cost of the order $c x$, the profit $f_s$ for scenario $s$ is given by
#
# $$
# \begin{align*}
# f_s & = r y_s + w (x - y_s) - c  x & \forall s \in S
# \end{align*}
# $$
#
# The average or expected profit is given by
#
# $$
# \begin{align*}
# \text{EVM} = \mathbb E[f] & = \sum_{s\in S} p_s f_s
# \end{align*}
# $$
#
# These calculations can be executed using operations on the pandas dataframe. Let's begin by calculating the expected demand.
#
# Below we create a pandas DataFrame object to store the scenario data.

# In[7]:

import numpy as np
import pandas as pd

# price information
r = 40
c = 12
w = 2

# scenario information
scenarios = {
    "sunny skies" : {"probability": 0.10, "demand": 650},
    "good weather": {"probability": 0.60, "demand": 400},
    "poor weather": {"probability": 0.30, "demand": 200},
}

df = pd.DataFrame.from_dict(scenarios).T
display(df)

# In[8]:

expected_demand = sum(df["probability"] * df["demand"])
print(f"Expected demand = {expected_demand}")

# Subsequent calculations can be done directly withthe  pandas dataframe holding the scenario data.

# In[9]:

df["order"] = expected_demand
df["sold"] = df[["demand", "order"]].min(axis=1)
df["salvage"] = df["order"] - df["sold"]
df["profit"] = r * df["sold"] + w * df["salvage"] - c * df["order"]

EVM = sum(df["probability"] * df["profit"])

print(f"Mean demand = {expected_demand}")
print(f"Expected value of the mean demand (EVM) = {EVM}")
display(df)

# ## Expected value of the stochastic solution (EVSS)
#
# The optimization problem is to find the order size $x$ that maximizes expected profit subject to operational constraints on the decision variables. The variables $x$ and $y_s$ are non-negative integers, while $f_s$ is a real number that can take either positive and negative values. The number of goods sold in scenario $s$ has to be less than the order size $x$ and customer demand $d_s$.
#
# The problem to be solved is
#
# $$
# \begin{align*}
# \text{EV} = & \max_{x, y_s} \mathbb E[F] = \sum_{s\in S} p_s f_s \\
# \text{subject to:} \\
# f_s & = r y_s + w(x - y_s) - c x & \forall s \in S\\
# y_s & \leq x & \forall s \in S \\
# y_s & \leq d_s & \forall s \in S
# \end{align*}
# $$
#
# where $S$ is the set of all scenarios under consideration.

# In[5]:

import pyomo.environ as pyo
import pandas as pd

# price information
r = 40
c = 12
w = 2

# scenario information
scenarios = {
    "sunny skies" : {"demand": 650, "probability": 0.1},
    "good weather": {"demand": 400, "probability": 0.6},
    "poor weather": {"demand": 200, "probability": 0.3},
}

# create model instance
m = pyo.ConcreteModel('Pop-up Shop')

# set of scenarios
m.S = pyo.Set(initialize=scenarios.keys())

# decision variables
m.x = pyo.Var(domain=pyo.NonNegativeIntegers)
m.y = pyo.Var(m.S, domain=pyo.NonNegativeIntegers)
m.f = pyo.Var(m.S, domain=pyo.Reals)

# objective
@m.Objective(sense=pyo.maximize)
def EV(m):
    return sum([scenarios[s]["probability"]*m.f[s] for s in m.S])

# constraints
@m.Constraint(m.S)
def profit(m, s):
    return m.f[s] == r*m.y[s] + w*(m.x - m.y[s]) - c*m.x

@m.Constraint(m.S)
def sales_less_than_order(m, s):
    return m.y[s] <= m.x

@m.Constraint(m.S)
def sales_less_than_demand(m, s):
    return m.y[s] <= scenarios[s]["demand"]

# solve
solver = pyo.SolverFactory('glpk')
results = solver.solve(m)

# display solution using Pandas
print("Solver Termination Condition:", results.solver.termination_condition)
print("Expected Profit:", m.EV())
print()
for s in m.S:
    scenarios[s]["order"] = m.x()
    scenarios[s]["sold"] = m.y[s]()
    scenarios[s]["salvage"] = m.x() - m.y[s]()
    scenarios[s]["profit"] = m.f[s]()

df = pd.DataFrame.from_dict(scenarios).T
display(df)

# Optimizing over all scenarios provides an expected profit of 8,920 €, an increase of 581 € over the base case of simply ordering the expected number of items sold. The new solution places a larger order. In poor weather conditions there will be more returns and lower profit that is more than compensated by the increased profits in good weather conditions.
#
# The addtional value that results from solve of this planning problem is called the **Value of the Stochastic Solution (VSS)**. The value of the stochastic solution is the additional profit compared to ordering to meet expected in demand. In this case,
#
# $$\text{VSS} = \text{EV} - \text{EVM} = 8,920 - 8,339 = 581$$

# ## Expected value with perfect information (EVPI)
#
# Maximizing expected profit requires the size of the order be decided before knowing what scenario will unfold. The decision for $x$ has to be made "here and now" with probablistic information about the future, but without specific information on which future will actually transpire.
#
# Nevertheless, we can perform the hypothetical calculation of what profit would be realized if we could know the future. We are still subject to the variability of weather, what is different is we know what the weather will be at the time the order is placed.
#
# The resulting value for the expected profit is called the **Expected Value of Perfect Information (EVPI)**.  The difference EVPI - EV is the extra profit due to having perfect knowledge of the future.
#
# To compute the expected profit with perfect information, we let the order variable $x$ be indexed by the subsequent scenario that will unfold. Given decision varaible $x_s$, the model for EVPI becomes
#
# $$
# \begin{align*}
# \text{EVPI} = & \max_{x_s, y_s} \mathbb E[f] = \sum_{s\in S} p_s f_s \\
# \text{subject to:} \\
# f_s & = r y_s + w(x_s - y_s) - c x_s & \forall s \in S\\
# y_s & \leq x_s & \forall s \in S \\
# y_s & \leq d_s & \forall s \in S
# \end{align*}
# $$
#
# The following implementation is a variation of the prior cell.

# In[6]:

import pyomo.environ as pyo
import pandas as pd

# price information
r = 40
c = 12
w = 2

# scenario information
scenarios = {
    "sunny skies" : {"demand": 650, "probability": 0.1},
    "good weather": {"demand": 400, "probability": 0.6},
    "poor weather": {"demand": 200, "probability": 0.3},
}

# create model instance
m = pyo.ConcreteModel('Pop-up Shop')

# set of scenarios
m.S = pyo.Set(initialize=scenarios.keys())

# decision variables
m.x = pyo.Var(m.S, domain=pyo.NonNegativeIntegers)
m.y = pyo.Var(m.S, domain=pyo.NonNegativeIntegers)
m.f = pyo.Var(m.S, domain=pyo.Reals)

# objective
@m.Objective(sense=pyo.maximize)
def EV(m):
    return sum([scenarios[s]["probability"]*m.f[s] for s in m.S])

# constraints
@m.Constraint(m.S)
def profit(m, s):
    return m.f[s] == r*m.y[s] + w*(m.x[s] - m.y[s]) - c*m.x[s]

@m.Constraint(m.S)
def sales_less_than_order(m, s):
    return m.y[s] <= m.x[s]

@m.Constraint(m.S)
def sales_less_than_demand(m, s):
    return m.y[s] <= scenarios[s]["demand"]

# solve
solver = pyo.SolverFactory('glpk')
results = solver.solve(m)

# display solution using Pandas
print("Solver Termination Condition:", results.solver.termination_condition)
print("Expected Profit:", m.EV())
print()
for s in m.S:
    scenarios[s]["order"] = m.x[s]()
    scenarios[s]["sold"] = m.y[s]()
    scenarios[s]["salvage"] = m.x[s]() - m.y[s]()
    scenarios[s]["profit"] = m.f[s]()

df = pd.DataFrame.from_dict(scenarios).T
display(df)

# ## Summary
#
# To summarize, have computed three different solutions to the problem of order size:
#
# * The expected value of the mean solution (EVM) is the expected profit resulting from ordering the number of items expected to sold under all scenarios.
#
# * The expected value of the stochastic solution (EVSS) is the expected profit found by solving an two-state optimization problem where the order size was the "here and now" decision without specific knowledge of which future scenario would transpire.
#
# * The expected value of perfect information (EVPI) is the result of a hypotherical case where knowledge of the future scenario was somehow available when then order had to be placed.
#
# For this example we found
#
# | Solution | Value (€) |
# | :------  | ----: |
# | Expected Value of the Mean Solution (EVM) | 8,399.0 |
# | Expected Value of the Stochastic Solution (EVSS) | 8,920.0 |
# | Expected Value of Perfect Information (EVPI) | 10,220.0 |
#
# These results verify our expectation that
#
# $$
# \begin{align*}
# EVM \leq EVSS \leq EVPI
# \end{align*}
# $$
#
# The value of the stochastic solution
#
# $$
# \begin{align*}
# VSS = EVSS - EVM = 581
# \end{align*}
# $$
#
# The value of perfect information
#
# $$
# \begin{align*}
# VPI = EVPI - EVSS = 1,300
# \end{align*}
# $$
#
#
# As one might expect, there is a cost that results from lack of knowledge about an uncertain future.


''' These give the derivations for Euler angles to rotation matrix and
Euler angles to quaternion.  We use the rotation matrix derivation only
in the tests.  The quaternion derivation is in the tests, and,
in more compact form, in the ``euler2quat`` code.

The rotation matrices operate on column vectors, thus, if ``R`` is the
3x3 rotation matrix, ``v`` is the 3 x N set of N vectors to be rotated,
and ``vdash`` is the matrix of rotated vectors::

   vdash = np.dot(R, v)

'''

from sympy import Symbol, cos, sin
from sympy.matrices import Matrix

def x_rotation(theta):
    ''' Rotation angle `theta` around x-axis
    http://en.wikipedia.org/wiki/Rotation_matrix#Dimension_three
    '''
    return Matrix([[1, 0, 0],
                   [0, cos(theta), -sin(theta)],
                   [0, sin(theta), cos(theta)]])

def y_rotation(theta):
    ''' Rotation angle `theta` around y-axis
    http://en.wikipedia.org/wiki/Rotation_matrix#Dimension_three
    '''
    return Matrix([[cos(theta), 0, sin(theta)],
                  [0, 1, 0],
                  [-sin(theta), 0, cos(theta)]])

def z_rotation(theta):
    ''' Rotation angle `theta` around z-axis
    http://en.wikipedia.org/wiki/Rotation_matrix#Dimension_three
    '''
    return Matrix([[cos(theta), -sin(theta), 0],
                  [sin(theta), cos(theta), 0],
                  [0, 0, 1]])

def qmult(q1, q2):
    ''' Multiply two quaternions

    Parameters
    ----------
    q1 : 4 element sequence
    q2 : 4 element sequence

    Returns
    -------
    q12 : shape (4,) array

    Notes
    -----
    See : http://en.wikipedia.org/wiki/Quaternions#Hamilton_product
    '''
    w1, x1, y1, z1 = q1
    w2, x2, y2, z2 = q2
    w = w1*w2 - x1*x2 - y1*y2 - z1*z2
    x = w1*x2 + x1*w2 + y1*z2 - z1*y2
    y = w1*y2 + y1*w2 + z1*x2 - x1*z2
    z = w1*z2 + z1*w2 + x1*y2 - y1*x2
    return w, x, y, z

def quat_around_axis(theta, axis):
    ''' Quaternion for rotation of angle `theta` around axis `axis`

    Parameters
    ----------
    theta : symbol
       angle of rotation
    axis : 3 element sequence
       vector (assumed normalized) specifying axis for rotation

    Returns
    -------
    quat : 4 element sequence of symbols
       quaternion giving specified rotation

    Notes
    -----
    Formula from http://mathworld.wolfram.com/EulerParameters.html
    '''
    # axis vector assumed normalized
    t2 = theta / 2.0
    st2 = sin(t2)
    return (cos(t2),
            st2 * axis[0],
            st2 * axis[1],
            st2 * axis[2])

def quat2mat(quat):
    ''' Symbolic conversion from quaternion to rotation matrix

    For a unit quaternion

    From: http://en.wikipedia.org/wiki/Rotation_matrix#Quaternion
    '''
    w, x, y, z = quat
    return Matrix([
            [1 - 2*y*y-2*z*z, 2*x*y - 2*z*w, 2*x*z+2*y*w],
            [2*x*y+2*z*w, 1-2*x*x-2*z*z, 2*y*z-2*x*w],
            [2*x*z-2*y*w, 2*y*z+2*x*w, 1-2*x*x-2*y*y]])

# Formula for rotation matrix given Euler angles and z, y, x ordering
M_zyx = (x_rotation(Symbol('x')) *
         y_rotation(Symbol('y')) *
         z_rotation(Symbol('z')))

# Formula for quaternion given Euler angles, z, y, x ordering
q_zrot = quat_around_axis(Symbol('z'), [0, 0, 1])
q_yrot = quat_around_axis(Symbol('y'), [0, 1, 0])
q_xrot = quat_around_axis(Symbol('x'), [1, 0, 0])

q_zyx = qmult(q_xrot, qmult(q_yrot, q_zrot))


#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time     : 2018/09/19 15:10
# @Author   : Iydon
# @File     : 2.3.py
# @Abstract : Homework auxiliary code.
import numpy as np

def Newton_method(f, df, start:float=0.0, step:int=1)->float:
	"""
	From 2.2.py.
	"""
	fun = lambda x: x-f(x)/df(x)
	if step:
		val = fun(start)
		for i in range(1,step):
			val = fun(val)
		return val
	else:
		return start

def secant_method(f, start:list, step:int=1) -> float:
    """
    From 3.py.
    """
    p = [i    for i in start]
    q = [f(i) for i in start]
    for i in range(step):
    	_p = p[-1] - q[-1]*(p[-1]-p[0])/(q[-1]-q[0])
    	p = [p[-1], _p]
    	q = [q[-1], f(_p)]
    return _p

def false_position(f, start:list, step:int=1) -> float:
    """
    From 3.py.
    """
    p = [i    for i in start]
    q = [f(i) for i in start]
    for i in range(step):
    	_p = p[-1] - q[-1]*(p[-1]-p[0])/(q[-1]-q[0])
    	_q = f(_p)
    	if _q*q[-1] < 0:
    		p[0] = p[-1]
    		q[0] = q[-1]
    	p[-1] = _p
    	q[-1] = _q
    return False

# ------- HOMEWORK -------
f  = lambda x: x**2-6
df = lambda x: 2*x
result = Newton_method(f, df, 1, 2)
print(result)

f  = lambda x: -x**3-np.cos(x)
df = lambda x: -3*x**2+np.sin(x)
result = Newton_method(f, df, -1, 2)
print(result)

f = lambda x: -x**3-np.cos(x)
result = secant_method(f, [-1,0], 2)
print(result)


import numpy as np
import matplotlib.pyplot as plt
from KnotVectors import OpenUniformKnotVector, PeriodicKnotVector
from BSpline import BSpline

#returns P which corresponds to multiplicity of each knot vector value
#and s which is the number of knot vector values that have multiple occurences
def KnotVectorMultiplicity(Knots):
    V, P = np.unique(Knots, False, False, True)
    s = np.sum(P[1:-1] > 1) #discard first/last since s only cares about internal values
    return V, P, s

def RaiseOrderTwoToThree(OriginalPoints, OriginalKnots):
    Values, P, s = KnotVectorMultiplicity(OriginalKnots)
    countPoints = np.size(OriginalPoints, axis=0)
    dimension = np.size(OriginalPoints, 1)
    countNewPoints = countPoints + 3 + s #3 is the new order
    NewPoints = np.zeros([countNewPoints, dimension])

    mpts = 0

    if OriginalKnots[0] < OriginalKnots[1]:
        NewPoints[0, :] = OriginalPoints[0, :] * 0.5
        mpts += 1

    NewPoints[mpts, :] = OriginalPoints[0, :]

    for i in range(1, countPoints):
        if OriginalKnots[i] < OriginalKnots[i + 1]:
            mpts += 1
            NewPoints[mpts, :] = (OriginalPoints[i, :] + OriginalPoints[i - 1, :]) * 0.5
        mpts += 1
        NewPoints[mpts, :] = OriginalPoints[i, :]

    if OriginalKnots[countPoints] < OriginalKnots[countPoints + 1]:
        mpts += 1
        NewPoints[mpts, :] = OriginalPoints[countPoints - 1, :] * 0.5

    NewKnots = np.asarray([])
    countP = len(P)
    for i in range(countP):
        NewKnots = np.append(NewKnots, np.ones(P[i] + 1) * Values[i], axis=0) #Duplicate knot values

    return NewPoints, NewKnots

if __name__ == "__main__":
    Points = np.array([[1., 1.], [2., 2.], [3., 2.], [4., 1.]])
    countPoints = np.size(Points, 0)
    oldOrder = 2
    Knots = OpenUniformKnotVector(oldOrder, countPoints, True)

    T = np.arange(0., 1., 0.01)

    SplineOld = BSpline(Points, oldOrder, Knots, T)

    plt.plot(Points[:, 0], Points[:, 1], "x")
    plt.plot(SplineOld[:, 0], SplineOld[:, 1])

    plt.show()

    newOrder = 3

    NewPoints, NewKnots = RaiseOrderTwoToThree(Points, Knots)

    SplineNew = BSpline(NewPoints, newOrder, NewKnots, T)

    plt.plot(NewPoints[:, 0], NewPoints[:, 1], "x")
    plt.plot(SplineNew[:, 0], SplineNew[:, 1])

    plt.show()


"""Python functions that solve PDEs."""
import numpy as np

def HeatEqn_FT(D, L, x, t, u_0):
    """
    Solve the 1-D Heat equation using the Fourier Transform.

    For periodic boundary conditions

    Arguments:
        inputs:
        D -- diffusion coefficient
        L -- length of spatial domain, the domain will be [-L/2, L/2)
        x -- 1D numpy array with spatial discretization
        t -- 1D numpy array with time discretization
        u_0 -- 1D numpy array with initial condition
        outputs:
        U -- 2D numpy array with solution to Heat equation, shape is
            (number of time steps, number of spatial points)
    """
    n = x.size
    k = (2 * np.pi / L) * np.fft.fftfreq(n, d=1 / n)
    u_0t = np.fft.fft(u_0)

    U = np.zeros((t.size, x.size))
    for ti in range(t.size):
        U[ti, :] = np.fft.ifft(np.exp(-D * k**2 * t[ti]) * u_0t)

    return U

def Burgers_Periodic(mu, eps, x, t_output, dt_factor, u_k):
    """Solve Burgers' equation.

    Burgers' equation:
        u_t + eps*u*u_x = mu*u_xx

    Solve using a second order FD method
    For periodic boundary conditions

    Arguments:
        inputs:
        mu -- diffusion coeffient/ viscosity
        eps -- strength of advection
        x -- 1D numpy array with spatial discretization
        t_output -- 1D numpy array with time discretization
        dt_factor -- divide dt from the above time discretization when solving
            (i.e. refine the time step for numerical stability,
            but only output every dt_factor steps)
        u_k -- 1D numpy array with initial condition
        outputs:
        U -- 2D numpy array with solution to Burgers' equation, shape is
            (number of time steps, number of spatial points)
    """
    n = x.size
    dx = x[1] - x[0]
    dt = (t_output[1] - t_output[0]) / dt_factor
    nt = (t_output.size - 1) * dt_factor + 1

    # Solve with FD scheme
    U = np.zeros((t_output.size, n))
    U[0, :] = u_k
    plus_ind = np.arange(1, n + 1) % n
    minus_ind = np.arange(-1, n - 1) % n
    for ti in range(1, nt):
        F_plus = (u_k**2 + u_k[plus_ind]**2) / 4
        F_minus = (u_k**2 + u_k[minus_ind]**2) / 4
        u_k = (u_k + dt *
               (mu * (u_k[plus_ind] - 2 * u_k + u_k[minus_ind])
                / dx**2 - eps * (F_plus - F_minus) / dx))

        if ti % dt_factor == 0:
            U[ti // dt_factor, :] = u_k

    return U

def KS_Periodic(x, tmax, ntime, u):
    """Solve the Kuramoto-Sivashinsky equation.

    Kuramoto-Sivashinsky equation:
        u_t = -u*u_x - u_xx - u_xxxx

    Solve in Fourier space using ETDRK4 time-stepping
        (See Kassam and Trefethen, 2005)
    For periodic boundary conditions

    Arguments:
        inputs:
        x -- 1D numpy array with spatial discretization
        tmax -- end time for simulation
        ntime -- number of time steps
        u -- 1D numpy array with initial condition
        outputs:
        U -- 2D numpy array with solution to KS equation, shape is
            (number of time steps, number of spatial points)
    """
    N = x.size
    v = np.fft.fft(u)

    # Precompute various ETDRK4 scalar quantities:
    h = 0.025
    k = (2 * np.pi / (x[-1] - 2 * x[0] + x[1])) * np.fft.fftfreq(N, d=1 / N)
    L = k**2 - k**4
    E = np.exp(h * L)
    E2 = np.exp(h * L / 2)
    M = 64
    r = np.exp(1j * np.pi * (np.arange(1, M + 1) - .5) / M)
    LR = h * np.tile(np.reshape(L, (N, 1)), (1, M)) + np.tile(r, (N, 1))
    Q = h * np.real(np.mean((np.exp(LR / 2) - 1) / LR, axis=1))
    f1 = h * np.real(np.mean(
        (-4 - LR + np.exp(LR) * (4 - 3 * LR + LR**2)) / LR**3, axis=1))
    f2 = h * np.real(np.mean(
        (2 + LR + np.exp(LR) * (-2 + LR)) / LR**3, axis=1))
    f3 = h * np.real(np.mean(
        (-4 - 3 * LR - LR**2 + np.exp(LR) * (4 - LR)) / LR**3, axis=1))

    # Main time-stepping loop:
    uu = u
    nmax = int(np.round(tmax / h))
    nplt = int(np.floor((tmax / (ntime - 1)) / h))
    g = -0.5j * k
    for n in range(nmax):
        Nv = g * np.fft.fft(np.real(np.fft.ifft(v))**2)
        a = E2 * v + Q * Nv
        Na = g * np.fft.fft(np.real(np.fft.ifft(a))**2)
        b = E2 * v + Q * Na
        Nb = g * np.fft.fft(np.real(np.fft.ifft(b))**2)
        c = E2 * a + Q * (2 * Nb - Nv)
        Nc = g * np.fft.fft(np.real(np.fft.ifft(c))**2)
        v = E * v + Nv * f1 + 2 * (Na + Nb) * f2 + Nc * f3
        if np.mod(n + 1, nplt) == 0:
            u = np.real(np.fft.ifft(v))
            uu = np.vstack((uu, u))

    return uu


import numpy as np
from scipy import ndimage

#
# GETWEIGHTMAP: compute the wieght map for data set
#
# @param masks
# @param w0
# @param sigma
#
# @Ref: https://arxiv.org/pdf/1505.04597.pdf
#       https://www.kaggle.com/piotrczapla/tensorflow-u-net-starter-lb-0-34/notebook
#
# Ecuation 2
#
# w(x) = w_c(x) + w_0*\exp(-\frac{(d_1(x)-d_2(x))^2}{2\sigma^2})
#
# where w_c : Ω → R is the weight map to balance the class frequencies,
# d_1 : Ω → R denotes the distance to the border of the nearest cell and
# d_2 : Ω → R the distance to the border of the second nearest cell.
# In our experiments we set w0 = 10 and σ ≈ 5 pixels.
#
#
#

def getunetweightmap( merged_mask, masks, w0=10, sigma=5, ):

    # WxHxN to NxWxH
    #masks = masks.transpose( (2,0,1) )

    weight = np.zeros(merged_mask.shape)
    # calculate weight for important pixels
    distances = np.array([ndimage.distance_transform_edt(m==0) for m in masks])
    shortest_dist = np.sort(distances, axis=0)
    # distance to the border of the nearest cell
    d1 = shortest_dist[0]
    # distance to the border of the second nearest cell
    d2 = shortest_dist[1] if len(shortest_dist) > 1 else np.zeros(d1.shape)

    w_b = np.exp(-(d1+d2)**2/(2*sigma**2)).astype(np.float32)
    w_c = getweightmap(merged_mask)
    w = w_c + w0*w_b

    #weight = 1 + (merged_mask == 0) * w
    weight = 1 + w

    return weight

#weight map
def getweightmap(mask):

    w_c = np.empty(mask.shape)
    classes = np.unique(mask)
    frecs = [ np.sum(mask == i)/float(mask.size) for i in classes ]

    # Calculate
    n = len(classes)
    for i in range( n ):
        w_c[mask == i] = 1 / (n*frecs[i])

    return w_c


# -*- coding: utf-8 -*-
"""
Spyder Editor

This is a temporary script file.
"""

import numpy as np
#import matplotlib.pyplot as plt

def loadDataSet(data_dir):
    dataMat = np.zeros((0,5))
    labelMat =np.zeros((0,1))
    fr = open(data_dir)
    for line in fr.readlines():
        lineArr = line.strip().split(',')
        dataMat=np.append(dataMat,[[1.0,float(lineArr[0]), float(lineArr[1]),float(lineArr[2]),float(lineArr[3])]],0)
        labelMat=np.append(labelMat,[[int(lineArr[4])]],0)
    return dataMat, labelMat

def sigmoid(x):
    return 1.0/(1+np.exp(-x)) #定义sigmoid函数

def grad_desc(dataMat,labelMat):
    m,n = np.shape(dataMat)
    a=0.001
    times=40
    weight = np.ones((n,1))
    for i in range(times):
        h= sigmoid(np.dot(dataMat,weight))
        error = h-labelMat
        weight = weight-a*np.dot(dataMat.T,error)
    return weight

def  random_grad_desc(dataMat,labelMat):
    a=0.001
    times = 90
    m,n = np.shape(dataMat)
    weight=np.ones((n,1))
    for i in range(times):
        for j in range(m):
            h=sigmoid(sum(np.dot(dataMat[j,:],weight)))
            error=h-labelMat[j]
            weight = weight-a*dataMat[j,:]*error
    return weight

def LR_classify(x,weight):
    prob = sigmoid(sum(np.dot(x,weight)))
    if prob > 0.5:
        return 1
    else:
        return 0

def LR_test(dataMat,labelMat,weight):
    errorCount = 0
    numTest = 0
    for i in range(dataMat.shape[0]):
        numTest += 1
        if LR_classify(dataMat[i,:],weight) != labelMat[i]:
            errorCount += 1
    errorRate = (float(errorCount)/numTest)
    return errorRate

if __name__ == '__main__':
    data_dir='data_banknote_authentication.txt'
    dataMat, labelMat = loadDataSet(data_dir)
    #print(dataMat, labelMat)
    #dataMat=np.array(dataMat)
    #labelMat=np.array(labelMat)
    dataMat_train = dataMat[0:int(.8*dataMat.shape[0]),:]
    dataMat_test = dataMat[int(.8*dataMat.shape[0]):,:]
    labelMat_train = labelMat[0:int(.8*labelMat.shape[0])]
    labelMat_test = labelMat[int(.8*labelMat.shape[0]):]

    weights=grad_desc(dataMat_train,labelMat_train)
##    weights=random_grad_desc(dataMat_train,labelMat_train)
    errorRate=LR_test(dataMat_test,labelMat_test,weights)
    print ("the error rate of this test is :",errorRate)


# -*- coding:UTF8 -*-
import numpy as np
import os,sys
import argparse
from tools import loadData
from tools import ulti
from LUFactorization import LU_factorization
from SchmidtProcedure import Schmidt_procedure
from HouseholderReduction import Housholder_reduction
from GivensReduction import Givens_reduction

# 获取当前工作路径
path = os.getcwd()

ap = argparse.ArgumentParser(description="Four Reduction Methods")
#选择使用的约简模型，四个选项'LU','QR','HR','GR'，其中LU代表LU factorization, QR代表Schmidt Procedure, HR代表Housholder Reduction, GR代表Givens Reduction!
ap.add_argument("--model", type=str, choices=['LU','QR','HR','GR'], default="LU",
                help="4 choices in ['LU','QR','HR','GR'], LU->LU factorization, QR->Schmidt Procedure, HR->Housholder Reduction, GR->Givens Reduction!")

ap.add_argument("--input", type=str, default="data/example1.txt",
                help="input example file path.")
# ap.add_argument("--egnum", type=int, default=1,
#                 help="number of examples to test!")

args = ap.parse_args()

if __name__ == "__main__":
    input_file=path+'/'+args.input
    # print(input_file)
    matrix, m, n= loadData.load_array(input_file, args.model)
    if matrix.size ==0:
        print("input Error!")
        sys.exit()

    if args.model == "LU":
        print("\nBe careful you have selected LU Factorization, the input should be a square matrix.\n")
    elif args.model == "QR":
        # 首先判断矩阵是否是列线性无关的
        mat_rank = ulti.rank_of_matrix(matrix,m,n)
        if mat_rank<n:
            print("Error!\nThe matrix with linearly dependent columns Can Not be uniquely factored as A=QR!\n\n")
            sys.exit()

    print("="*50,"\norigin matrix type: {m} * {n}" .format(m=m,n=n),"\nOrigin Matrix A = ")
    ulti.print_array(matrix, m, n)
    print("="*50, "\nProcessing:")
    if args.model == "LU":
        L,U,P = LU_factorization(matrix, m, n)
        print("L=")
        ulti.print_array(L,m,m)
        print("U=")
        ulti.print_array(U,m,m)
        print("P=")
        ulti.print_array(P,m,m)
    elif args.model == "QR":
        Q,R = Schmidt_procedure(matrix,m,n)
        print("Q=")
        ulti.print_array(Q,m,n)
        print("R=")
        ulti.print_array(R,n,n)
    elif args.model == "HR":
        Q,R = Housholder_reduction(matrix,m,n)
        print("Q=")
        ulti.print_array(Q,m,m)
        print("R=")
        ulti.print_array(R,m,n)
    elif args.model=="GR":
        Q,R = Givens_reduction(matrix,m,n)
        print("Q=")
        ulti.print_array(Q,m,m)
        print("R=")
        ulti.print_array(R,m,n)


import numpy as np
from scipy.sparse.linalg import LinearOperator, cg, gmres, lgmres

from cfdpy.derivative.finiteDifferenceMethods import centralFDM

class poisson2(object):
    def __init__(self, nx, ny, dx=1., dy=1.):
        self.nx = nx
        self.ny = ny
        self.dx = dx
        self.dy = dy
        self.p_shape = (self.ny, self.nx)
        self.A_shape = (self.nx*self.ny, self.nx*self.ny)
        self.derivative = centralFDM(order=6, highestDerivative=2)
        self.exitCode = 0
        self.A = LinearOperator(self.A_shape, matvec=self.lhs)

    def lhs(self, p_flatten):
        p = np.reshape(p_flatten, self.p_shape)
        p = ( self.derivative(p, h=self.dx, axis=-1, derivative=2)
            + self.derivative(p, h=self.dy, axis=-2, derivative=2))
        return p.flatten()

    def rhs(self, u, v):
        return ( self.derivative(u, h=self.dx, axis=-1)
               + self.derivative(v, h=self.dy, axis=-2)).flatten()

    def solve(self, u, v, method="gmres"):
        if method=="gmres":
            p_flatten, self.exitCode = gmres(A=self.A, b=self.rhs(u, v))
        elif method=="cg":
            p_flatten, self.exitCode = cg(A=self.A, b=self.rhs(u, v))
        elif method=="lgmres":
            p_flatten, self.exitCode = lgmres(A=self.A, b=self.rhs(u, v))
        else:
            p_flatten = np.linalg.solve(self.A(np.identity(self.nx*self.ny)), self.rhs(u, v))
        return np.reshape(p_flatten, self.p_shape)


import numpy as np
from random import Random

def fitness(population, n):

    #index_fit = 0
    population_fit = []
    flag = False
    for i in range(len(population)):
      chromosome = []
      if (len(population) != n):
        chromosome.append(population[i])
      else:
        chromosome = population
        flag = True

      horizontal_clash = abs(len(chromosome) - len(np.unique(chromosome)))
      diagonal_clashes = 0
      # calculate diagonal clashes
      for i in range(len(chromosome)):
          for j in range(i,len(chromosome)):
              if ( i != j):
                  dx = abs(i-j)
                  dy = abs(chromosome[i] - chromosome[j])
                  if(dx == dy):
                      diagonal_clashes += 1

      fit = 28 - (horizontal_clash + diagonal_clashes)
      population_fit.append(fit)
      if (flag):
        return population_fit
      #index_fit += 1
    return population_fit

def select(population, fit):

    temp = population
    a = []
    for i in range(len(temp)):
      a.append(i)
    size = 1
    fit_lst = fit
    p = []
    for i in range(len(fit_lst)):
      t2 = 0.0
      t1 = float(fit_lst[i])
      for j in range(len(fit_lst)):
        t2 += fit_lst[j]
      p.append(t1/t2)

    #p = [.31, .29, 0.26, 0.14]

    index_num = np.random.choice(a, size, True, p)
    rand_select = temp[int(index_num)]
    return rand_select

def crossover(x, y):

    r = Random()
    idx = r.randint(3,5)
    x = x[0:idx]
    y = y[idx:8]
    #child = x + y
    #child = x[0:idx] + y[idx:8]
    child = np.concatenate((x , y))
    return child
    #return x[0:idx] + y[idx:8]

def mutate(child):

    r = Random()
    idx = r.randint(0, 7) #random index
    child[idx] = r.randint(1,8) #replaces selected random index with a random integer

    return child

def GA(population, n, mutation_threshold = 0.3):

    gen_max = 100000
    gen_counter = gen_max
    target_fitness = 28
    while gen_counter > 0:
      new_population = []
      for i in range(len(population)):
        x = select(population, fitness(population, n))
        y = select(population, fitness(population, n))
        child = crossover(x, y)
        r = Random()
        if r.uniform(0, 1) < mutation_threshold:
          child = mutate(child)
        fit_child = fitness(child,n)
        if (fit_child[0] == target_fitness):
          print(child, " found in ", gen_max-gen_counter," generations\n")
          print("The max fitness value = ", fit_child)
          return child
        new_population.append(child)
      population = new_population
      gen_counter -= 1
    print("nothing found in ", gen_max, " genrations\n")
    return None

'''for 8 queen problem, n = 8'''
n = 8

'''start_population denotes how many individuals/chromosomes are there
  in the initial population n = 8'''
start_population = 10

'''if you want you can set mutation_threshold to a higher value,
   to increase the chances of mutation'''
mutation_threshold = 0.3

'''creating the population with random integers between 0 to 7 inclusive
   for n = 8 queen problem'''
population = np.random.randint(0, n, (start_population, n))

'''calling the GA function'''
GA(population, n, mutation_threshold)


import numpy as np
import numpy.linalg as la
from io import StringIO

#def print_mat(stream, mat):
def print_mat(mat):

    stream = StringIO()
    np.savetxt(stream, mat, fmt="%.3f")
    print( stream.getvalue() )

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

# transition matrix L
L = np.array([
    [0,   1/2, 1/3, 0, 0,   0   ],
    [1/3, 0,   0,   0, 1/2, 0   ],
    [1/3, 1/2, 0,   1, 0,   1/2 ],
    [1/3, 0,   1/3, 0, 1/2, 1/2 ],
    [0,   0,   0,   0, 0,   0   ],
    [0,   0,   1/3, 0, 0,   0   ]
])

# output transition matrix
print_mat(mat=L)

#  compute eigenvalue and eigenvector
e_val, e_vacs = la.eig(L)

# take the eigenvector with eigenvalue = 1
vec = np.transpose(e_vacs)[0]

#  take only real part
vec_real = vec.real
vec_real = vec_real * 100.0/sum(vec_real)

# output eigenvector
print_mat(mat=vec_real)


#!/usr/bin/env python
# -*- encoding: utf-8 -*-
"""
Topic: 矩阵和线性代数
Desc :
"""
import numpy as np
import numpy.linalg

def matrix_linear():
    m = np.matrix([[1,-2,3],[0,4,5],[7,8,-9]])
    print(m)

    # Return transpose  转置矩阵
    print(m.T)

    # Return inverse  # 逆矩阵
    print(m.I)

    # Create a vector and multiply
    v = np.matrix([[2],[3],[4]])
    print(v)
    print(m * v)

    # Determinant 行列式
    print(numpy.linalg.det(m))

    # Eigenvalues 特征值
    print(numpy.linalg.eigvals(m))

    # Solve for x in m*x = v
    x = numpy.linalg.solve(m, v)
    print(x)
    print(m * x)
    print(v)

if __name__ == '__main__':
    matrix_linear()


import numpy as np
import math

def normalize(v):
    m = np.linalg.norm(v)
    if m == 0:
        return v
    return v / m

def translate(xyz):
    x, y, z = xyz[:3]
    return np.matrix([[1,0,0,x],
                      [0,1,0,y],
                      [0,0,1,z],
                      [0,0,0,1]], dtype=np.float32)

def scale(xyz):
    x, y, z = xyz[:3]
    return np.matrix([[x,0,0,0],
                      [0,y,0,0],
                      [0,0,z,0],
                      [0,0,0,1]], dtype=np.float32)

def rotate(a, xyz):
    x, y, z = normalize(xyz)
    a = math.radians(a)
    s = math.sin(a)
    c = math.cos(a)
    nc = 1 - c
    return np.matrix([[x*x*nc +   c, x*y*nc - z*s, x*z*nc + y*s, 0],
                      [y*x*nc + z*s, y*y*nc +   c, y*z*nc - x*s, 0],
                      [x*z*nc - y*s, y*z*nc + x*s, z*z*nc +   c, 0],
                      [           0,            0,            0, 1]], dtype=np.float32)

def rotate_x(a):
    a = math.radians(a)
    s = math.sin(a)
    c = math.cos(a)
    return np.matrix([[1,0,0,0],
                      [0,c,-s,0],
                      [0,s,c,0],
                      [0,0,0,1]],  dtype=np.float32)

def rotate_y(a):
    a = math.radians(a)
    s = math.sin(a)
    c = math.cos(a)
    return np.matrix([[c,0,s,0],
                      [0,1,0,0],
                      [-s,0,c,0],
                      [0,0,0,1]], dtype=np.float32)

def rotate_z(a):
    a = math.radians(a)
    s = math.sin(a)
    c = math.cos(a)
    return np.matrix([[c,-s,0,0],
                      [s,c,0,0],
                      [0,0,1,0],
                      [0,0,0,1]], dtype=np.float32)

def look_at(eye, center, up=[0, 1, 0]):
    eye = np.array(eye, dtype=np.float32).flatten()[:3]
    center = np.array(center, dtype=np.float32).flatten()[:3]
    up = np.array(up, dtype=np.float32).flatten()[:3]

    f = normalize(center - eye)
    s = normalize(np.cross(f, up))
    u = np.cross(s, f)

    M = np.matrix(np.identity(4), dtype=np.float32)
    M[:3,:3] = np.vstack([s, u, -f])
    M[0, 3] = -np.dot(s, eye)
    M[1, 3] = -np.dot(u, eye)
    M[2, 3] =  np.dot(f, eye)
    return M


import numpy as np

def sigmf(x, params):
    if not isinstance(params, list):
        raise TypeError("Params should be a list with two values.")
    if len(params) != 2:
        raise TypeError("Number of parameters are incorrect. Expected 2 values in the list.")
    if not (isinstance(params[0], float) and isinstance(params[1], float)):
        raise TypeError("Parameters should be in float.")

    a = params[0] # Controls width of the sigmoid region
    c = params[1] # Offset or bias. This is the center value of the sigmoid
    return 1/(1 + np.exp(-a*(x - c)))


'''
ANKIT KHANDELWAL
15863
Exercise 6
'''

import numpy as np
import pandas as pd

pitch = pd.read_csv("pitch.txt", sep='\t', header=None)
n1 = len(pitch)
pitch_array = np.zeros(n1)
for i in range(n1):
    pitch_array[i] = pitch[0][i]

def FFT(x):
    N = len(x)
    if N == 1:
        return x
    X_even = FFT(x[::2])
    X_odd = FFT(x[1::2])
    factor = np.exp(-2j * np.pi * np.arange(N) / N)
    return np.concatenate([X_even + factor[:N // 2] * X_odd, X_even + factor[N // 2:] * X_odd])

c = FFT(pitch_array)
c1 = np.fft.fft(pitch_array)
print(c, 'Using user defined function.\n')
print(c1, 'Using built-in function.\n')

diff = abs(c - c1)
max_error = max(diff)
print(max_error, 'This is the max error between the two.')

Ankit Khandelwal_HW4/Exercise 6/exercise 6.py


import numpy as np
from scipy.stats import zscore

def similarity(X, Y, method):
    '''
    SIMILARITY Computes similarity matrices

    Usage:
        sim = similarity(X, Y, method)

    Input:
    X   N1 x M matrix
    Y   N2 x M matrix
    method   string defining one of the following similarity measure
           'SMC', 'smc'             : Simple Matching Coefficient
           'Jaccard', 'jac'         : Jaccard coefficient
           'ExtendedJaccard', 'ext' : The Extended Jaccard coefficient
           'Cosine', 'cos'          : Cosine Similarity
           'Correlation', 'cor'     : Correlation coefficient

    Output:
    sim Estimated similarity matrix between X and Y
        If input is not binary, SMC and Jaccard will make each
        attribute binary according to x>median(x)

    Copyright, Morten Morup and Mikkel N. Schmidt
    Technical University of Denmark '''

    X = np.mat(X)
    Y = np.mat(Y)
    N1, M = np.shape(X)
    N2, M = np.shape(Y)

    method = method[:3].lower()
    if method=='smc': # SMC
        X,Y = binarize(X,Y);
        sim = ((X*Y.T)+((1-X)*(1-Y).T))/M
    elif method=='jac': # Jaccard
        X,Y = binarize(X,Y);
        sim = (X*Y.T)/(M-(1-X)*(1-Y).T)
    elif method=='ext': # Extended Jaccard
        XYt = X*Y.T
        sim = XYt / (np.log( np.exp(sum(np.power(X.T,2))).T * np.exp(sum(np.power(Y.T,2))) ) - XYt)
    elif method=='cos': # Cosine
        sim = (X*Y.T)/(np.sqrt(sum(np.power(X.T,2))).T * np.sqrt(sum(np.power(Y.T,2))))
    elif method=='cor': # Correlation
        X_ = zscore(X,axis=1,ddof=1)
        Y_ = zscore(Y,axis=1,ddof=1)
        sim = (X_*Y_.T)/(M-1)
    return sim

def binarize(X,Y=None):
    ''' Force binary representation of the matrix, according to X>median(X) '''
    x_was_transposed = False
    if Y is None:
        if X.shape[0] == 1:
            x_was_transposed = True
            X = X.T;

        Xmedians = np.ones((np.shape(X)[0],1)) * np.median(X,0)
        Xflags = X>Xmedians
        X[Xflags] = 1; X[~Xflags] = 0

        if x_was_transposed:
            return X.T
        return X
    else:
        #X = np.matrix(X); Y = np.matrix(Y);
        #XYmedian= np.median(np.bmat('X; Y'),0)
        #Xmedians = np.ones((np.shape(X)[0],1)) * XYmedian
        #Xflags = X>Xmedians
        #X[Xflags] = 1; X[~Xflags] = 0
        #Ymedians = np.ones((np.shape(Y)[0],1)) * XYmedian
        #Yflags = Y>Ymedians
        #Y[Yflags] = 1; Y[~Yflags] = 0
        return [binarize(X,None),binarize(Y,None)]

## Example
#import numpy as np
#from similarity import binarize2
#A = np.asarray([[1,2,3,4,5],[6,7,8,9,10],[1,2,3,4,5],[6,7,8,9,10]]).T
#binarize2(A,['a','b','c','d'])
def binarize2(X,columnnames):
    X = np.concatenate((binarize(X),1-binarize(X)),axis=1)

    new_column_names = []
    [new_column_names.append(elm) for elm in [name+' 50th-100th percentile' for name in columnnames]]
    [new_column_names.append(elm) for elm in [name+' 0th-50th percentile' for name in columnnames]]

    return X, new_column_names