import numpy as np
from numba import jit

def mean_square_error(y_true: np.ndarray, y_pred: np.ndarray) -> float:
    """
    Calculate MSE loss

    Parameters
    ----------
    y_true: ndarray of shape (n_samples, )
        True response values
    y_pred: ndarray of shape (n_samples, )
        Predicted response values

    Returns
    -------
    MSE of given predictions
    """
    return np.mean(np.power(y_true - y_pred, 2)).item()

def misclassification_error(y_true: np.ndarray, y_pred: np.ndarray, normalize: bool = True) -> float:
    """
    Calculate misclassification loss

    Parameters
    ----------
    y_true: ndarray of shape (n_samples, )
        True response values
    y_pred: ndarray of shape (n_samples, )
        Predicted response values
    normalize: bool, default = True
        Normalize by number of samples or not

    Returns
    -------
    Misclassification of given predictions
    """
    sumy = 0
    for i in range(len(y_true)):
        if y_true[i] != y_pred[i]:
            sumy += 1
    return sumy / len(y_true) if normalize else sumy

@jit(nopython=True)
def weighted_misclassification_error(y_true: np.ndarray, y_pred: np.ndarray, normalize: bool = True) -> float:
    """
    Calculate misclassification loss

    Parameters
    ----------
    y_true: ndarray of shape (n_samples, )
        True response values
    y_pred: ndarray of shape (n_samples, )
        Predicted response values
    normalize: bool, default = True
        Normalize by number of samples or not

    Returns
    -------
    Misclassification of given predictions
    """
    sumy = 0
    for i in range(len(y_true)):
        if np.sign(y_true[i]) != np.sign(y_pred[i]):
            sumy += np.abs(y_true[i]).item()
    return sumy / np.sum(np.abs(y_true)) if normalize else sumy

def accuracy(y_true: np.ndarray, y_pred: np.ndarray) -> float:
    """
    Calculate accuracy of given predictions

    Parameters
    ----------
    y_true: ndarray of shape (n_samples, )
        True response values
    y_pred: ndarray of shape (n_samples, )
        Predicted response values

    Returns
    -------
    Accuracy of given predictions
    """
    sumy = 0
    for i in range(len(y_true)):
        if y_true[i] == y_pred[i]:
            sumy += 1
    return sumy / len(y_true)

def cross_entropy(y_true: np.ndarray, y_pred: np.ndarray) -> float:
    """
    Calculate the cross entropy of given predictions

    Parameters
    ----------
    y_true: ndarray of shape (n_samples, )
        True response values
    y_pred: ndarray of shape (n_samples, )
        Predicted response values

    Returns
    -------
    Cross entropy of given predictions
    """
    raise NotImplementedError()

if __name__ == '__main__':
    y_true = np.array([279000, 432000, 326000, 333000, 437400, 555950])
    y_pred = np.array(
        [199000.37562541, 452589.25533196, 345267.48129011, 345856.57131275, 563867.1347574, 395102.94362135])
    print(mean_square_error(y_true, y_pred))


import numpy as np

def loadDataSet():
	dataMat = []; labelMat = []
	fr = open('testSet.txt')
	for line in fr.readlines():
		lineArr = line.strip().split()
		dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])])
		labelMat.append(int(lineArr[2]))
	return dataMat, labelMat

def sigmod(inX):
	return 1.0 / (1+np.exp(-inX))

def gradAscent(dataMatIn, classLabel):
	'''
	batch gradient ascent
	批量梯度上升算法
	'''
	dataMatrix = np.mat(dataMatIn) #100*3
	labelMatrix = np.mat(classLabel).transpose() #100*1
	m, n = np.shape(dataMatrix)
	alpha = 0.001
	maxCycles = 500
	weights = np.ones((n,1)) #3*1

	for k in range(maxCycles):
		h = sigmod(dataMatrix*weights) #100*1
		error = labelMatrix - h #100*1
		weights = weights + alpha*dataMatrix.transpose()*error #3*1

		#getA()将矩阵转换为ndarray
	return weights.getA()

def stochasticGradAsent0(dataMatrix, classLabel):
	m, n = np.shape(dataMatrix)

	alpha = 0.01
	weights = np.ones(n) #3

	for i in range(m):
		h = sigmod(np.dot(dataMatrix[i], weights))
		error = classLabel[i] - h
		weights = weights + alpha*dataMatrix[i]*error

	return weights

def stochasticGradAsent1(dataMatrix, classLabel, numIter=150):
	m, n = np.shape(dataMatrix)

	# alpha = 0.01
	weights = np.ones(n) #3

	for j in range(numIter):
		dataIndex = list(range(m))

		for i in range(m):
			alpha = 4 / (1.0+j+i) + 0.01

			randIndex = int(np.random.uniform(0, len(dataIndex)))

			h = sigmod(np.dot(dataMatrix[randIndex], weights))
			error = classLabel[randIndex] - h
			weights = weights + alpha*dataMatrix[randIndex]*error
			del(dataIndex[randIndex])

	return weights

def plotBestFit(weights):
	import matplotlib.pyplot as plt

	#将矩阵转换为ndarray
	# weights = wei.getA()

	dataMat, labelMat = loadDataSet()
	dataArr = np.array(dataMat)
	n = np.shape(dataArr)[0]

	xcord1 = []; ycord1 = []
	xcord2 = []; ycord2 = []
	for i in range(n):
		if int(labelMat[i]) == 1:
			xcord1.append(dataArr[i,1])
			ycord1.append(dataArr[i,2])
		else:
			xcord2.append(dataArr[i,1])
			ycord2.append(dataArr[i,2])

	fig = plt.figure()
	ax = fig.add_subplot(111)
	ax.scatter(xcord1, ycord1, s=30, c='red', marker='s')
	ax.scatter(xcord2, ycord2, s=30, c='green')
	x = np.arange(-3.0, 3.0, 0.1)
	y = (-weights[0] - weights[1]*x) / weights[2]
	ax.plot(x, y)
	plt.xlabel('X')
	plt.ylabel('Y')
	plt.show()

#使用logistic回归从疝气病症预测病马的死亡率
def classifyVector(inX, weights):
	prob = sigmod(sum(inX*weights))
	# prob = sigmod(np.dot(inX, weights))
	# print(prob)

	if prob > 0.5:
		return 1
	else:
		return 0

def colicTest():
	frTrain = open('horseColicTraining.txt')
	frTest = open('horseColicTest.txt')

	trainingSet = []; trainingLabels = []
	for line in frTrain.readlines():
		# \t 相当于tab键
		currLine = line.strip().split('\t')
		lineArr = []
		for i in range(21):
			lineArr.append(float(currLine[i]))
		trainingSet.append(lineArr)
		trainingLabels.append(float(currLine[21]))

	trainWeights = stochasticGradAsent1(np.array(trainingSet), trainingLabels, 500)

	errorCount = 0
	numTestVec = 0.0

	for line in frTest.readlines():
		numTestVec += 1
		currLine = line.strip().split('\t')
		lineArr = []

		for i in range(21):
			lineArr.append(float(currLine[i]))

		classifyRes = classifyVector(np.array(lineArr), trainWeights)
		# print(classifyRes, ' and ', currLine[21])
		if classifyRes != int(currLine[21]):
			errorCount += 1

	errorRate = float(errorCount) / numTestVec

	print('the error rate of this test is: ', errorRate)

	return errorRate

def multiTest():
	numTests = 10
	errorSum = 0.0

	for k in range(numTests):
		errorSum += colicTest()

	print('after %d iterations the average error rate is: %f' %(numTests, errorSum/float(numTests)))

if __name__ == '__main__':

	dataArr, labelMat = loadDataSet()
	# weights = gradAscent(dataArr, labelMat)
	# plotBestFit(weights)

	# weights2 = stochasticGradAsent1(np.array(dataArr), labelMat)
	# plotBestFit(weights2)

	multiTest()


#!/usr/bin/python3

import numpy as np
from sympy.matrices import Matrix
from sympy import symbols, atan2, sqrt

# Conversion Factors
rtd = 180/np.pi
dtr = np.pi/180

# Fixed Axis X-Y-Z Rotation Matrix
R_XYZ = Matrix([[ 0.353553390593274, -0.306186217847897, 0.883883476483184],
                [ 0.353553390593274,  0.918558653543692, 0.176776695296637],
                [-0.866025403784439,               0.25, 0.433012701892219]])

# Identify useful terms from rotation matrix
r31 = R_XYZ[2,0]
r11 = R_XYZ[0,0]
r21 = R_XYZ[1,0]
r32 = R_XYZ[2,1]
r33 = R_XYZ[2,2]

# Euler Angles from Rotation Matrix
# sympy synatx for atan2 is atan2(y, x)
beta  = atan2(-r31, sqrt(r11 * r11 + r21 * r21)) * rtd
gamma = atan2(r32, r33) * rtd
alpha = atan2(r21, r11) * rtd

print("alpha is = ",alpha*dtr, "radians", "or ", alpha, "degrees")
print("beta  is = ",beta*dtr,  "radians", "or ", beta, "degrees")
print("gamma is = ",gamma*dtr, "radians", "or ", gamma, "degrees")


import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import argparse

#function to compute the cost function
def compute_cost(X,Y,theta):
    '''
    Input: X=Design matrix of dim (no of samples, no of features+1 )
           Y=response vector of dim (no of samples,1)
           theta=parameter vector of dim (no of features+1,1)
    Output: cost= mean squared error of the hypothesis function of dim (1,1)
    '''
    #dimension check when X contains a single sample/row(incase of stochastic gradient descent)
    if(X.ndim==1):
        X=X.reshape(1,-1)
        Y=Y.reshape(-1,1)
    cost=np.sum(np.power(Y-np.dot(X,theta),2))/(2*X.shape[0])
    cost=cost.reshape(-1,1)
    return cost

#function to update parameters
def update_parameters(X,Y, theta, learning_rate):
    '''
    Input: X=Design matrix of dim (no of samples, no of features+1)
           Y=response vector of dim (no of samples,1)
           theta=parameter vector of dim (no of features+1,1)
           learning_rate= learning rate is a scalar, dim=0
    Output: theta= updated parameter vector of dim (no of features+1, 1)
    '''
    #dimension check when X contains a single sample/row(incase of stochastic gradient descent)
    if(X.ndim==1):
        X=X.reshape(1,-1)
        Y=Y.reshape(-1,1)
    error=Y-np.dot(X,theta)
    theta=theta+learning_rate*(1/X.shape[0])*np.transpose(np.sum(error*X,axis=0,keepdims=True))
    return theta

#function to perform batch gradient descent
def gradient_descent(X,Y,eps,learning_rate):
    '''
    Input: X=Design matrix of dim (no of samples, no of features+1)
           Y=response vector of dim (no of samples,1)
           learning_rate= learning rate is a scalar, dim=0
           eps= hreshold value for stopping criterion
    Output: values is a dictionary contains "cost_array"= stores cost, dim(no of iterations,1) and
                        "theta_array"= stores parameter, dim(no of feattures+1,no of iteeraton) and
                        "theta"= stores final parameters, dim(no of features+1,1) and
                        "count"= scalar, stores no of iterations, dim=0
    '''
    #initializing parameters
    theta=np.array([0,0]).reshape(-1,1)

    cost_new=compute_cost(X,Y,theta)

    #to keep track of no of iterations
    count=0

    #arrays to store the cost and parameter values for plotting
    cost_array=np.array([])
    theta_array=np.array([])

    while True:
        cost_old=cost_new
        count=count+1

        #updating the parameters and computing the cost
        theta=update_parameters(X,Y, theta, learning_rate)
        cost_new=compute_cost(X,Y,theta)

        cost_array=np.append(cost_array,cost_new)
        theta_array=np.append(theta_array,theta)

        #check for stopping criterion
        if(np.abs(cost_old-cost_new)<eps):
            break
    cost_array=cost_array.reshape(-1,1)
    theta_array=theta_array.reshape(cost_array.shape[0],-1).T

    values={"cost_array":cost_array, "theta_array":theta_array,"theta":theta,"count":count}

    return values

#function to print fitted parameter values
def print_values():
    print("Parameter vector is:\n"+str(theta))
    print("No of iterations is: "+str(count))

#function to plot the fitted graph
def plot_graph(X,Y,theta):
    '''
    Input: X=Design matrix of dim (no of samples, no of features+1)
           Y=response vector of dim (no of samples,1)
           theta=parameter vector of dim (no of features+1,1)
    '''
    #plot the training data points
    plt.scatter(X[:,1],Y,label="sample points",color="red")

    #plot the fitted line
    y_hat=theta[0]+theta[1]*X[:,1]
    plt.plot(X[:,1],y_hat,label= "predicted function")

    plt.xlabel('Acidity of wine')
    plt.ylabel('Density of wine')
    plt.title("Fitting data using linear regression and gradient Descent")
    plt.legend(loc="lower right")

    plt.show()

#function to plot the contour cost function wrt the parameters
def plot_contour(X,Y,theta0_array,theta1_array):
    '''
    Input: X=Design matrix of dim (no of samples, no of features+1)
           Y=response vector of dim (no of samples,1)
           theta0_array=parameter vector of dim (no of iterations,1),intercept term
           theta1_array=parameter vector of dim (no of features+1,1),corresponding to first feature
    '''
    #creating mesh grid
    x=np.linspace(-0.1,1.2,100)
    y=np.linspace(-0.1,1.3,100)
    x,y=np.meshgrid(x,y)

    #reshaping x and y grid for calculation purpose
    grid= np.vstack((x.reshape(1,-1),y.reshape(1,-1)))

    #computing cost at the grid points
    cost=np.sum(np.power((Y-np.dot(X,grid)),2),axis=0,keepdims=True)/(2*m)
    cost=cost.reshape(x.shape)

    fig,ax = plt.subplots()
    plt.xlabel('Acidity of wine')
    plt.ylabel('Density of wine')
    plt.title("Contour plot of the cost function")
    ax.contour(x,y,cost,20)
    plt.scatter(theta0_array,theta1_array,s=4)
    plt.show()

#plot the surface of cost function
def plot_surface(X,Y,theta0_array, theta1_array,cost_array,elev,azim):
    '''
    Input: X=Design matrix of dim (no of samples, no of features+1)
           Y=response vector of dim (no of samples,1)
           theta0_array=parameter vector of dim (no of iterations,1),intercept term
           theta1_array=parameter vector of dim (no of features+1,1),corresponding to first feature
           cost_array=dim(no of iterations,1)
           elev= 3d surface vertical angle view
           azim=3d surface x-y plane angle view
    '''
    x=np.linspace(-1,2.5,100)
    y=np.linspace(-2.5,2,100)
    x,y=np.meshgrid(x,y)

    #reshaping x and y grid for calculation purpose
    grid= np.vstack((x.reshape(1,-1),y.reshape(1,-1)))

    #computing cost at the grid points
    cost=np.sum(np.power((Y-np.dot(X,grid)),2),axis=0,keepdims=True)/(2*m)
    cost=cost.reshape(x.shape)

    fig=plt.figure(figsize=[12,8])
    ax = fig.gca(projection='3d')
    ax.plot_surface(x,y,cost,cmap='viridis', edgecolor='none',alpha=0.6)
    ax.view_init(elev,azim)
    ax.scatter3D(theta0_array,theta1_array,cost_array,color="black",s=8)
    plt.xlabel('Acidity of wine')
    plt.ylabel('Density of wine')
    ax.set_zlabel('cost function')
    plt.title("Surface plot of the cost function")
    plt.show()

#load data from files
trainX=np.loadtxt("linearX.csv").reshape(-1,1)
X=(trainX-np.mean(trainX))/np.std(trainX)
Y=np.loadtxt("linearY.csv").reshape(-1,1)

m=X.shape[0]
#stacking a column vector of 1's and creating the design matrix, X contains sample as row
X=np.hstack((np.ones((m,1)),X))

parser = argparse.ArgumentParser()
parser.add_argument('--lr',type = float)
parser.add_argument('--eps',type = float)
args = parser.parse_args()

learning_rate = args.lr
eps = args.eps

values=gradient_descent(X,Y,eps,learning_rate)

theta=values["theta"]
count=values["count"]
theta0_array=values["theta_array"][0,:]
theta1_array=values["theta_array"][1,:]
cost_array=values["cost_array"]

print_values()
plot_graph(X,Y,values["theta"])
plot_contour(X,Y,theta0_array,theta1_array)
plot_surface(X,Y, theta0_array.T,theta1_array.T,cost_array,elev=10,azim=100)


import numpy

def eigen_example():
    A = numpy.random.randn(5,10)
    #A = numpy.array([[1, 2, 3], [3, 4, 7], [2, 7, 9]], dtype=numpy.float64)
    print A
    w, U = numpy.linalg.eig(A)
    L = numpy.diag(w)
    B = numpy.dot(U, numpy.dot(L, U.T))
    print B
    print "Loss =", numpy.linalg.norm(A - B)
    #P = numpy.array([[1, 2], [3, 4]])
    #Q = numpy.array([[5, 6], [7, 8]])
    #print numpy.dot(P, Q)
    pass

def svd_example(k):
    n = 10
    m = 100
    A = numpy.random.randn(n, m)
    #A = numpy.array([[1, 2, 3], [3, 4, 7], [2, 7, 9]], dtype=numpy.float64)
    #print "A =", A
    U, w, V = numpy.linalg.svd(A)
    U = U[:, :k]
    V = V[:k, :]
    L = numpy.zeros((k, k), dtype=float)
    predLoss = 0
    for i in range(k):
        #print w[i]
        L[i,i] = w[i]
    for i in range(k, n):
        predLoss += w[i] ** 2
    #print "U = ", U.shape
    #print "V = ", V.shape
    #print "L =", L.shape
    B = numpy.dot(U, numpy.dot(L, V))
    #print B
    print k, "Loss =", numpy.linalg.norm(A - B), "predLoss =", predLoss
    #P = numpy.array([[1, 2], [3, 4]])
    #Q = numpy.array([[5, 6], [7, 8]])
    #print numpy.dot(P, Q)
    pass

if __name__ == '__main__':
    #eigen_example()
    for k in range(1, 11):
        svd_example(k)


# -*- coding: utf-8 -*-
"""
Created on Mon Sep 20 20:10:02 2021

@author: joseph.lindquist
"""

import numpy as np
import matplotlib.pyplot as plt

def divDiff(x0,y0):
    """
    Compute the Newton divided difference coefficients for an interpolant:

    Input:
        x0 - vector of "x"
        y0 - vector of "y"
    Output:
        nCoef - vector of newton coefficients
    """
    n = len(x) # Number of data points
    coef = np.zeros((n,n)) # create a matrix that is n x n
    nCoef = np.zeros(n)
    nCoef[0]=y0[0] # seed a_0
    for i in range(n): # fill in f[x_n] using y0 values
        coef[i,0]=y0[i]
    for i in range(1,n): # cycle through 1,2,...,n including the nth
        for j in range(1,i+1):
            coef[i,j]=(coef[i,j-1]-coef[i-1,j-1])/(x0[i]-x0[i-j])
        nCoef[i]=coef[i,i] # record coefficient on diagonal for a_i
    print(coef)
    return nCoef

def newtonEval(coef,x0,xE):
    """
    Evaluate the polynomial given by the Newton coefficients of the form:
        P_n(x)=a0 + a1(x-x0) + a2(x-x0)(x-x1) + ... + a_n(x-x0)...(x-x_n-1)
    Input:
        coef - array returned by the divDiff function
        x0   - vector of data points
        xE   - node to interpolate at
    Output:
        val  - value of interpolant at x=xE, i.e. P(xE)
    Dependencies:
        Requires use of divDiff
    """
    #We need to figure this out in class!
    n = len(coef)-1
    val = coef[n]
    i = n-1
    while i >= 0:
        val = val * (xE-x[i])+coef[i]
        i = i - 1
    return val

def unitStep(n):
    """
    Creates n interpolation points for a unit step function, centered at 0.
    Uses uniformly spaced interpolation points.

    Input:
        n - number of interpolation points desired

    Output:
        x - vector of "x"
        y - vector of "y"
    """
    x = np.linspace(-1,1,n) # create some interpolation points
    y = np.ones(len(x)) # "y" values for the given interpolation points above
    for i in range(len(x)):
        if x[i] <= 0:
            y[i]=0
    return x,y

def unitStepCheb(n):
    """
    Creates n interpolation points for a unit step function, centered at 0
    Uses the roots of Chebychev polynomials for interpolation points.

    Input:
        n - number of interpolation points desired

    Output:
        x - vector of "x"
        y - vector of "y"
    """
    x = np.zeros(n)
    y = np.ones(n)
    for i in range(n):
        x[i] = np.cos(((2*i+1)*np.pi)/(2*n))
        if x[i] <= 0:
            y[i]=0
    return x,y
# Some Examples

#x=np.array([1,1.3,1.6,1.9,2.2]) # Example 3.3.1
#y=np.array([0.7651977,0.620086,0.4554022,0.2818186,0.1103623])

#x = np.linspace(-1,3,10) # x values for the interpolation nodes
#y = np.cos(x) # "y" values for the cosine interpolation nodes

#x,y = unitStep(20)

x,y = unitStepCheb(20)

# Find the Newton Divided Difference Coefficients
coef=divDiff(x,y)
print(coef)

# Interpolate at a point.
print(newtonEval(coef,x,0))

left = -1
right = 1
nPoints = 100
xInterp = np.linspace(left,right,nPoints)
est = np.zeros(nPoints)
for i in range(nPoints):
    est[i]=newtonEval(coef,x,xInterp[i])

# Plotting routine with legend
plt.plot(x,y,"o",color="k", label='Interp Points')
plt.plot(xInterp,est, label = 'Interpolant')
plt.ylim([-3,3])
plt.xlabel('x')
plt.ylabel('y')
plt.title('Plot of the function')
plt.grid(True)
plt.legend()
plt.show


import numpy as np
import pandas as pd

# -----------------------------------
# 회귀
# -----------------------------------
# rmse

from sklearn.metrics import mean_squared_error

# y_true - 실젯값, y_pred - 예측값
y_true = [1.0, 1.5, 2.0, 1.2, 1.8]
y_pred = [0.8, 1.5, 1.8, 1.3, 3.0]

rmse = np.sqrt(mean_squared_error(y_true, y_pred))
print(rmse)
# 0.5532

# -----------------------------------
# 이진 분류
# -----------------------------------
# 혼동행렬

from sklearn.metrics import confusion_matrix

# 0, 1로 표현되는 이진 분류의 실젯값과 예측값
y_true = [1, 0, 1, 1, 0, 1, 1, 0]
y_pred = [0, 0, 1, 1, 0, 0, 1, 1]

tp = np.sum((np.array(y_true) == 1) & (np.array(y_pred) == 1))
tn = np.sum((np.array(y_true) == 0) & (np.array(y_pred) == 0))
fp = np.sum((np.array(y_true) == 0) & (np.array(y_pred) == 1))
fn = np.sum((np.array(y_true) == 1) & (np.array(y_pred) == 0))

confusion_matrix1 = np.array([[tp, fp],
                              [fn, tn]])

print(confusion_matrix1)
# array([[3, 1],
#        [2, 2]])

# 사이킷런의 metrics 모듈의 confusion_matrix로도 작성 가능하지만,
# 혼동행렬의 요소 배치가 다르므로 주의가 필요
confusion_matrix2 = confusion_matrix(y_true, y_pred)
print(confusion_matrix2)
# array([[2, 1],
#        [2, 3]])

# -----------------------------------
# 정확도(accuracy)
# -----------------------------------
from sklearn.metrics import accuracy_score

# 0, 1로 표현되는 이진 분류의 실젯값과 예측값
y_true = [1, 0, 1, 1, 0, 1, 1, 0]
y_pred = [0, 0, 1, 1, 0, 0, 1, 1]
accuracy = accuracy_score(y_true, y_pred)
print(accuracy)
# 0.625

# -----------------------------------
# logloss
# -----------------------------------
from sklearn.metrics import log_loss

# 0, 1로 나타나는 이진 분류의 실젯값과 예측 확률
y_true = [1, 0, 1, 1, 0, 1]
y_prob = [0.1, 0.2, 0.8, 0.8, 0.1, 0.3]

logloss = log_loss(y_true, y_prob)
print(logloss)
# 0.7136

# -----------------------------------
# 다중 클래스 분류
# -----------------------------------
# multi-class logloss

from sklearn.metrics import log_loss

# 3 클래스 분류의 실젯값과 예측값
y_true = np.array([0, 2, 1, 2, 2])
y_pred = np.array([[0.68, 0.32, 0.00],
                   [0.00, 0.00, 1.00],
                   [0.60, 0.40, 0.00],
                   [0.00, 0.00, 1.00],
                   [0.28, 0.12, 0.60]])
logloss = log_loss(y_true, y_pred)
print(logloss)
# 0.3626

# -----------------------------------
# 다중 레이블 분류
# -----------------------------------
# mean_f1, macro_f1, micro_f1

from sklearn.metrics import f1_score

# 다중 레이블 분류의 실젯값·예측값은 평가지표 계산상으로는 행 데이터 × 클래스의 두
# 값 행렬로 해야 다루기 쉬움
# 실젯값 - [[1,2], [1], [1,2,3], [2,3], [3]]
y_true = np.array([[1, 1, 0],
                   [1, 0, 0],
                   [1, 1, 1],
                   [0, 1, 1],
                   [0, 0, 1]])

# 예측값 - [[1,3], [2], [1,3], [3], [3]]
y_pred = np.array([[1, 0, 1],
                   [0, 1, 0],
                   [1, 0, 1],
                   [0, 0, 1],
                   [0, 0, 1]])

# mean-f1는 행 데이터마다 F1-score를 계산하여 평균을 취함
mean_f1 = np.mean([f1_score(y_true[i, :], y_pred[i, :]) for i in range(len(y_true))])

# macro-f1에서는 행 데이터마다 F1-score를 계산하여 평균을 취함
n_class = 3
macro_f1 = np.mean([f1_score(y_true[:, c], y_pred[:, c]) for c in range(n_class)])

# micro-f1에서는 행 데이터 × 클래스의 쌍으로 TP/TN/FP/FN을 계산하여 F1-score를 구함
micro_f1 = f1_score(y_true.reshape(-1), y_pred.reshape(-1))

print(mean_f1, macro_f1, micro_f1)
# 0.5933, 0.5524, 0.6250

# scikit-learn 메소드를 사용하여 계산 가능
mean_f1 = f1_score(y_true, y_pred, average='samples')
macro_f1 = f1_score(y_true, y_pred, average='macro')
micro_f1 = f1_score(y_true, y_pred, average='micro')
print(mean_f1, macro_f1, micro_f1)

# -----------------------------------
# 클래스간 순서관계가 있는 다중 클래스 분류
# -----------------------------------
# quadratic weighted kappa

from sklearn.metrics import confusion_matrix, cohen_kappa_score

# quadratic weighted kappa을 계산하는 함수
def quadratic_weighted_kappa(c_matrix):
    numer = 0.0
    denom = 0.0

    for i in range(c_matrix.shape[0]):
        for j in range(c_matrix.shape[1]):
            n = c_matrix.shape[0]
            wij = ((i - j) ** 2.0)
            oij = c_matrix[i, j]
            eij = c_matrix[i, :].sum() * c_matrix[:, j].sum() / c_matrix.sum()
            numer += wij * oij
            denom += wij * eij

    return 1.0 - numer / denom

# y_true는 실젯값 클래스 목록, y_pred는 예측값 클래스 목록
y_true = [1, 2, 3, 4, 3]
y_pred = [2, 2, 4, 4, 5]

# 혼동행렬을 계산
c_matrix = confusion_matrix(y_true, y_pred, labels=[1, 2, 3, 4, 5])

# quadratic weighted kappa를 계산
kappa = quadratic_weighted_kappa(c_matrix)
print(kappa)
# 0.6154 (소수점 5번째자리 반올림)

# scikit-learn의 메소드로도 계산 가능
kappa = cohen_kappa_score(y_true, y_pred, weights='quadratic')
print(kappa)
# 0.6154 (소수점 5번째자리 반올림)

# -----------------------------------
# Recommendation(추천)
# -----------------------------------
# MAP@K

# K=3、행의 수는 5개, 클래스는 4종류
K = 3

# 각 행의 실젯값
y_true = [[1, 2], [1, 2], [4], [1, 2, 3, 4], [3, 4]]

# 각 행에 대한 예측값 - K = 3이므로, 일반적으로 각 행에 각각 3개까지 순위를 매겨 예측
y_pred = [[1, 2, 4], [4, 1, 2], [1, 4, 3], [1, 2, 3], [1, 2, 4]]

# 각 행의 average precision을 계산하는 함수
def apk(y_i_true, y_i_pred):
    # y_pred가 K이하의 길이이고 모든 요소가 달라야 함
    assert (len(y_i_pred) <= K)
    assert (len(np.unique(y_i_pred)) == len(y_i_pred))

    sum_precision = 0.0
    num_hits = 0.0

    for i, p in enumerate(y_i_pred):
        if p in y_i_true:
            num_hits += 1
            precision = num_hits / (i + 1)
            sum_precision += precision

    return sum_precision / min(len(y_i_true), K)

# MAP@K을 계산하는 함수
def mapk(y_true, y_pred):
    return np.mean([apk(y_i_true, y_i_pred) for y_i_true, y_i_pred in zip(y_true, y_pred)])

# MAP@K을 요청
print(mapk(y_true, y_pred))
# 0.65

# 정답 수가 같아도 순서가 다르면 점수도 다름
print(apk(y_true[0], y_pred[0]))
print(apk(y_true[1], y_pred[1]))
# 1.0, 0.5833


#!/usr/bin/env python3
"""
Advanced Linear Algebra Module
"""
import numpy as np

def definiteness(matrix):
    """
    Calculates the definiteness of a matrix.
    matrix is a numpy.ndarray of shape (n, n) whose definiteness should be
    calculated
    If matrix is not a numpy.ndarray, raise a TypeError with the message
    matrix must be a numpy.ndarray
    If matrix is not a valid matrix, return None

    Return: the string Positive definite, Positive semi-definite, Negative
    semi-definite, Negative definite, or Indefinite if the matrix is positive
    definite, positive semi-definite, negative semi-definite, negative
    definite of indefinite, respectively

    If matrix does not fit any of the above categories, return None
    """
    if type(matrix) != np.ndarray:
        raise TypeError('matrix must be a numpy.ndarray')
    if len(matrix.shape) == 1 or matrix.shape[0] != matrix.shape[1]:
        return None
    if not np.linalg.eig(matrix):
        return None
    if not (matrix.transpose() == matrix).all():
        return None

    try:
        eig = np.linalg.eigvals(matrix)
        if all(eig > 0):
            return 'Positive definite'
        if all(eig >= 0):
            return 'Positive semi-definite'
        if all(eig < 0):
            return 'Negative definite'
        if all(eig <= 0):
            return 'Negative semi-definite'
        return 'Indefinite'
    except Exception:
        return None


from numpy import linspace, exp

def demand_curve(t0=0.0, t1=5.0, tm=None, ymax=1.0, ymin=0.0, k=6.0):
    '''calcula os pontos da curva de demanda

    parametros
    ----------

    t0 : preço mínimo de compra/venda
    t1 : preço máximo de compra/venda
    ymin : valor mínimo de demanda
    ymax: valor máximo de demanda
    k : inclinação da função logística
    '''
    if not tm:
        tm = t0 + (t1 - t0) / 2.0 # ponto medio da curva

    t = linspace(t0, t1, 50)
    y = ymax * (1.0 / (1.0 + exp(k*(t - tm)))) + ymin * (1.0 / (1.0 + exp(-k*(t - tm))))
    return t, y

def utility_curve(t0=0.0, t1=5.0, min_price=(1.0, 0.0), max_power=(5.0, 50.0)):
    '''calcula os pontos da curva de demanda

    parametros
    ----------

    t0 : preço mínimo de compra/venda
    t1 : preço máximo de compra/venda
    ymin : valor mínimo de demanda
    ymax: valor máximo de demanda
    k : inclinação da função logística
    '''

    t = linspace(t0, t1, 50)
    a = min_price[1] - max_power[1]
    b = min_price[0] - max_power[0]
    c = min_price[0] * max_power[1] - min_price[1] - max_power[0]
    y = - (a / b) * t - c / b
    return t, y


from AutoDiff import AutoDiff
import numpy as np

def all_derivatives(func, in_vars, point):
    '''
    Function that calculates the value of the input function at the input point and all its partial derivatives

    :params func: (function) function to evaluate whose input is a list of variables
            in_vars: (list)  list of variables to use when calculating the values of the input function
            point: (list)    list of values of each input variable at the input point

    :returns: out_val (scalar) the value of the input function at the input point
              out_dervs (numpy array , 1 dimensional) an array of the 1st derivative values of each input variable
                                                      at the input point

    :dependencies: requires class AutoDiff from module AutoDiff, package numpy imported ad np

    Example:

    f(x,y) = x^2 + y^2

    def func(vars):
        return vars[0]**2 + vars[1]**2

    a, b = all_derivatives(func, ['x','y'], [3,2])
    print(a, b)
    13.0, [6.0, 4.0]

    '''
    auto_diff_vars = []   # list to hold AutoDiff objects, one for each var in in_vars
    out_dervs =[]         # list to hold derivative values, one for each var in in_vars

    # Make AutoDiff objects
    for var, pt in zip(in_vars, point):
        var = AutoDiff(pt, 0)
        auto_diff_vars.append(var)

    # Calculate the value of func at the input point
    f = func(auto_diff_vars)
    out_val = f.val

    # Calculate the partial derivatives of func at the input point
    # Go through AutoDiff objects in auto_diff_vars
    # and during each pass change the derv value of 1 variable to 1, while others are held at 0
    # and calculate the partial derivative
    for i in range(len(auto_diff_vars)):
        auto_diff_vars[i].derv = 1
        f = func(auto_diff_vars)
        out_dervs.append(f.derv)
        auto_diff_vars[i].derv = 0

    return out_val, np.array(out_dervs)

def multi_func_all_derivatives(functions, in_vars, point):
    '''
    Function that calculates the value of all input functions at the input point and all their partial derivatives
    producing a numpy array of output values and a numpy 2D array (matrix) of partial derivatives, the Jacobian

    :params func: (functions) list of function to evaluate whose input is a list of variables
            in_vars: (list)   list of variables to use when calculating the values of the input functions
            point: (list)     list of values of each input variable at the input point

    :returns: out_vals (numpy array 1 dimensional) the values of the input functions at the input point
              out_dervs_matrix (numpy array 2 dimensional) a matrix of the 1st derivative values of each input variable
                        at the input point, the Jacobian.

    :dependencies: requires class AutoDiff from module AutoDiff, function all_derivatives from this module,
                            All_derivatives, and the package numpy imported as np

    Example:

    f(x,y) = x^2 + y^2

    (x,y) = x^2*y^2

    def func1(vars):
        return vars[0]**2 + vars[1]**2

    def func2(vars):
        return vars[0]**2*vars[1]**2

    a, b = multi_func_all_derivatives([func1,func2] , ['x','y'], [3,2])
    print(a, b)
    [13. 36.] [[ 6.  4.], [24. 36.]]

    '''
    out_vals = []
    out_dervs_matrix =[]

    # for each function in functions list
    # run all_derivatives and store output
    for func in functions:
        val, dervs = all_derivatives(func, in_vars, point)
        out_vals.append(val)
        out_dervs_matrix.append(dervs)

    return np.array(out_vals), np.array(out_dervs_matrix)


from sklearn.metrics import mean_squared_error, mean_absolute_error
from scipy.stats import pearsonr
from math import sqrt
from numpy import std

from util.constants import RMSE_KEY, CORR_COEFF_KEY, STANDARD_DEVIATION_KEY

def rename(newname):
    def decorator(f):
        f.__name__ = newname
        return f

    return decorator

@rename(RMSE_KEY)
def rmse(y_actual, y_predicted):
    """
    Calculates sqrt(1/n * sum((y_actual-y_predicted)^2))
    :param y_actual: Correct values
    :param y_predicted: Predicted values
    :return: root mean square
    """
    return sqrt(mean_squared_error(y_actual, y_predicted))

def mae(y_actual, y_predicted):
    """
    Calculates 1/n * sum(|y_actual-y_predicted|)
    :param y_actual: Correct values
    :param y_predicted: Predicted values
    :return: root mean square
    """
    return mean_absolute_error(y_actual, y_predicted)

@rename(CORR_COEFF_KEY)
def correlation_coefficient(y_actual, y_predicted):
    coeff, _ = pearsonr(y_actual, y_predicted)
    return coeff

@rename(STANDARD_DEVIATION_KEY)
def standard_deviation(value_list):
    return std(value_list)


import numpy as np
from scipy.stats import norm

# Underlying informations
S0 = 100.0
sigma = 0.2

# European option informations
T = 1.0
K = 110.0
r = 0.1

def d1():
    return (np.log(S0/K)+(r+0.5*sigma**2)*T)/(sigma*np.sqrt(T))

def d2():
    return d1() - sigma*np.sqrt(T)

def price_BS():
    return S0*norm.cdf(d1())-K*np.exp(-r*T)*norm.cdf(d2())

def price_approx():
    return 0.4*S0*sigma*np.sqrt(T)

print(price_BS())
print(price_approx())
print((price_approx()-price_BS())/price_BS())


import math
import numpy as np

from utils.structure import Shape

class CoreAlign(object):
    '''
    Methods that define core matrix transformations
    '''
    def translate(self, shape, Tx, Ty):
        '''
        Translate a shape according to translation parameters
        '''
        return Shape([shape.x + Tx, shape.y + Ty])

    def normalize(self, shape):
        '''
        Perform isomorphic scaling in order to normalize shapes
        See Amy Ross on GPA p.5

        in: target Shape
        out: scaled Shape object
        '''
        return Shape([shape.vector/np.linalg.norm(shape.vector)])

    def scale_and_rotate(self, subject, s, theta, inverse=False):
        '''Rotate over theta and scale by s'''
        rotation_matrix = np.array([
                            [s*math.cos(theta), -1*s*math.sin(theta)],
                            [s*math.sin(theta), s*math.cos(theta)]
                            ])
        if inverse:
            return Shape(np.dot(rotation_matrix.T, subject.matrix))
        else:
            return Shape(np.dot(rotation_matrix, subject.matrix))

    def transform(self, target, pose_parameters):
        '''
        Perform transformations to move target.

        in: Shape target,
            translation params Tx, Ty,
            scaling param s,
            rotation angle theta
        out: transformed Shape
        '''
        # normalize target to avoid multiple scaling
        target = self.normalize(target)
        # get pose parameters and perform transformations
        Tx, Ty, s, theta = pose_parameters
        scaled_and_rotated = self.scale_and_rotate(target, s, theta)
        return self.translate(scaled_and_rotated, Tx, Ty)

    def invert_transform(self, target, pose_parameters):
        '''
        Computes an inverse transformation of target
        '''
        # get pose parameters and invert transform
        Tx, Ty, s, theta = pose_parameters
        translated = self.translate(target, -1*Tx, -1*Ty)
        return self.scale_and_rotate(translated, 1/s, theta, inverse=True)

class TransformationFinder(object):
    '''
    Methods to get the correct pose parameters of a shape with
    respect to a target shape. For scaling and rotation, first
    get the transformation parameters a and b.
    '''
    def get_transformation_parameters(self, subject, target):
        '''
        Compute the parameters for scaling and rotation.
        As in Cootes (2000), if:
            a = (x1*x2)/|x1|^2
            b = sum1_n(x1i*y2i - y1i*x2i)/|x1|^2
        then
            s^2 = a^2 + b^2
            theta = tan^-1(b/a)
        '''
        # compute denominator
        denom = np.linalg.norm(subject.vector)**2
        # compute numerators
        num_a = np.dot(subject.vector, target.vector.T)
        num_b = np.sum(subject.x.dot(target.y) - subject.y.dot(target.x))
        return num_a/denom, num_b/denom

    def find_scale(self, a, b):
        return math.sqrt(a**2 + b**2)

    def find_rotation_angle(self, a, b):
        '''Return angle'''
        return math.atan(b/a)

    def find_translation(self, subject, target):
        '''
        Translation params = the difference between the centroids
        '''
        scX, scY = subject.centroid()
        tcX, tcY = target.centroid()
        return (tcX - scX, tcY - scY)

class Aligner(CoreAlign, TransformationFinder):
    '''
    Alignment class that combines the alignment methods from CoreAlign and the
    transformation variable finding methods from CoreFinder.
    '''
    def get_pose_parameters(self, subject, target):
        '''
        Find the pose parameters to align subject with target.
        In: 1xC array shape1, shape2
        Out: X_t, Y_t params that define the translation,
            s, defines the scaling
            theta, defines the rotation
        '''
        # find/perform transformations
        Tx, Ty = self.find_translation(subject, target)
        # compute a and b
        a, b = self.get_transformation_parameters(subject, target)
        s = self.find_scale(a, b)
        theta = self.find_rotation_angle(a, b)

        return (Tx, Ty, s, theta)


import re
import math
from collections import Counter
import numpy as np

text1 = 'Nicole a mangé du singe'
text2 = 'Nicole a mangé du rat'

class Similarity():
    def compute_cosine_similarity(self, string1, string2):
        # intersects the words that are common
        # in the set of the two words
        intersection = set(string1.keys()) & set(string2.keys())
        # dot matrix of vec1 and vec2
        numerator = sum([string1[x] * string2[x] for x in intersection])

        # sum of the squares of each vector
        # sum1 is the sum of text1 and same for sum2 for text2
        sum1 = sum([string1[x]**2 for x in string1.keys()])
        sum2 = sum([string2[x]**2 for x in string2.keys()])

        # product of the square root of both sum(s)
        denominator = math.sqrt(sum1) * math.sqrt(sum2)
        if not denominator:
            return 0.0
        else:
            return round(numerator / float(denominator), 4)

    def text_to_vector(self, text):
        WORD = re.compile(r'\w+')
        words = WORD.findall(text)
        return Counter(words)

    # Jaccard Similarity
    def tokenize(self, string):
        return string.lower().split(" ")

    def jaccard_similarity(self, string1, string2):
        intersection = set(string1).intersection(set(string2))
        union = set(string1).union(set(string2))
        return len(intersection) / float(len(union))

similarity = Similarity()

# vector space
vector1 = similarity.text_to_vector(text1)
vector2 = similarity.text_to_vector(text2)

# split words into tokens
token1 = similarity.tokenize(text1)
token2 = similarity.tokenize(text2)

cosine = similarity.compute_cosine_similarity(vector1, vector2)
print('Cosine Similarity:', cosine)

jaccard = similarity.jaccard_similarity(token1, token2)
print('Jaccard Similarity:', jaccard)


"""
filters.py - various image filtering operation

"""
#Author @otivedani

import numpy as np

# Section 0: 2d edge convolution
def simple_edge_gradients(img):
    _img_ = np.pad(img, (1,1), 'symmetric').astype(np.float_)

    # #[ 1 , 0 ,-1 ]
    gX = (_img_[:,:-2] - _img_[:,2:])[1:-1,:]
    # #[[1,
    # #  0,
    # # -1]]
    gY = (_img_[:-2,:] - _img_[2:,:])[:,1:-1]

    return gX, gY

# Section 1: numpy-based 2D convolutional filter, improved version from sobelY_HC and sobelX_HC
def conv_filter(img, h_kernel, v_kernel, clip=False):
    """
    Convolve 2d array horizontally then vertically.

    Parameters :
	------------
        img: numpy 2darray
        h_kernel: 1darray
        v_kernel: 1darray
        clip: if true - normalize to range(0,255)

    Return :
    --------
    img (dot) (h(dot)v)

    """
    h_klen = len(h_kernel)
    v_klen = len(v_kernel)

    h_pad = (h_klen-1)//2
    v_pad = (v_klen-1)//2

    result_h = np.zeros((img.shape[0]+(2*h_pad)+2,img.shape[1]))
    result_v = np.zeros(img.shape)

    # img2 = np.pad(img,((1+(h_pad),1+(h_pad)),(1+(v_pad),1+(v_pad))),'constant', constant_values=((0, 0),(0, 0)))
    img2 = np.pad(img,((1+(h_pad),1+(h_pad)),(1+(v_pad),1+(v_pad))),'reflect')

    #work like matlab.conv2(u,v,A)
    #TODO kill looping (vectorize)
    for i in range(h_klen):
        # result_h += h_kernel[i]*img2[:,1+i:len(img)+1+i]
        result_h += h_kernel[i]*img2[:,-(len(img[0])+1+i):-(1+i)]
    for j in range(v_klen):
        # result_v += v_kernel[j]*result_h[1+j:len(img)+1+j]
        result_v += v_kernel[j]*result_h[-(len(img)+1+j):-(1+j)]

    if clip:
        return np.clip(result_v,0,255)
    else:
        return result_v

#-- end of Section 1

# Section 2 : Magnitude, Angle vector calculation
def toPolar(gX, gY, signed=False, dtype='float'):
    """
    Parameters :
	------------
        gX: numpy 2darray - cartesian coordinate
        gY: numpy 2darray - cartesian coordinate
        signed: if true - change to range(0,360) == similar to 'cv2'
                if false - change to range(0,180)(default)
    Return :
    --------
    polar coordinate (w,a)
    """

    _basis = 360 if signed else 180

    # still return (-180,180)
    _ang = np.degrees(np.arctan2(gY,gX))

    mag = np.sqrt((np.square(gX))+(np.square(gY)))
    ori = np.where(_ang < 0, _ang + _basis, _ang)

    return mag.astype(dtype), ori.astype(dtype)
#-- end of Section 2

# Section 3 : x-position, y-position vector calculation
def toCart(ori, mag, signed=False, dtype='float'):
    """
    Parameters :
	------------
        ori: array-like numpy, in degrees
        mag: array-like numpy
        signed: if true - change to range(0,360)
                if false - change to range(0,180)

    Return :
    --------
    cartesian coordinate (x,y)
    """

    _basis = 360 if signed else 180

    x = mag * np.cos(ori*np.pi/_basis)
    y = mag * np.sin(ori*np.pi/_basis)

    return x.astype(dtype), y.astype(dtype)
#-- end of Section 3

# Section 4 :
# TBA
#-- end of Section 4


#!/usr/bin/python3

import numpy as np
import matplotlib.pyplot as plt

COLOR = ['#4285f4', '#db4437', '#f4b400', '#0f9d58', '#303030']

WEIGHTS = np.array([
    [10, 0], [10, 2], [10, 4], [10, 6], [8, 6],
    [8, 8], [6, 8], [6, 10], [4, 10], [2, 10]
], dtype = np.float)

def drawLine(ax, x1, y1, x2, y2, color = 'black', alpha = 1.0, label = None):
    ax.arrow(x1, y1, x2 - x1, y2 - y1, width = 0, linewidth = 1,
        color = color, alpha = alpha, label = label)

def drawCircle(ax, x, y, radius, color = 'black', alpha = 1.0, label = None):
    circle = plt.Circle((x, y), radius, linewidth = 1, fill = False,
        edgecolor = color, facecolor = 'white', alpha = alpha)
    ax.add_artist(circle)

def drawL1Region(ax, C):
    drawLine(ax, C, 0, 0, C, color = COLOR[4], alpha = 0.8)
    drawLine(ax, C, 0, 0, -C, color = COLOR[4], alpha = 0.8)
    drawLine(ax, -C, 0, 0, C, color = COLOR[4], alpha = 0.8)
    drawLine(ax, -C, 0, 0, -C, color = COLOR[4], alpha = 0.8)

def drawL2Region(ax, C):
    drawCircle(ax, 0, 0, C, color = COLOR[4], alpha = 0.8)

def drawSquareRegion(ax, C):
    drawLine(ax, C, -C, C, C, color = COLOR[4], alpha = 0.8)
    drawLine(ax, -C, C, C, C, color = COLOR[4], alpha = 0.8)
    drawLine(ax, -C, C, -C, -C, color = COLOR[4], alpha = 0.8)
    drawLine(ax, C, -C, -C, -C, color = COLOR[4], alpha = 0.8)

def l1Regularize(weights, C):
    reg = np.empty_like(weights, dtype = np.float)
    for i in range(len(weights)):
        x, y = weights[i, 0], weights[i, 1]
        if y - x <= -C:
            reg[i] = C, 0
            continue
        elif y - x >= C:
            reg[i] = 0, C
            continue
        d = (x + y - C) / 2
        reg[i] = x - d, y - d
    return reg

def l2Regularize(weights, C):
    norm = np.linalg.norm(weights, axis = 1)
    return C * weights / np.column_stack((norm, norm))

def lpRegularize(weights, C):
    return np.minimum(weights, C)

def calcSparsity(arr, axis):
    return np.size(arr, axis) - np.count_nonzero(arr, axis)

def main(weights, region, C, plot_fname, idx = []):
    fig, ax = plt.subplots()
    ax.set_aspect('equal')

    inv_idx = np.ones(len(weights))
    inv_idx[idx] = 0
    inv_idx = inv_idx == 1
    ax.scatter(weights[inv_idx, 0], weights[inv_idx, 1], color = COLOR[0], label = 'Unconstrained')
    ax.scatter(weights[idx, 0], weights[idx, 1], color = COLOR[2], label = 'Unconstrained')
    if region == 'L1':
        drawL1Region(ax, C)
        weights_reg = l1Regularize(weights, C)
    elif region == 'L2':
        drawL2Region(ax, C)
        weights_reg = l2Regularize(weights, C)
    else:
        drawSquareRegion(ax, C)
        weights_reg = lpRegularize(weights, C)

    sparsity = calcSparsity(weights, axis = 1)
    sparsity_reg = calcSparsity(weights_reg, axis = 1)
    print(f'Number of weights with higher regularization sparsity: {np.sum(sparsity_reg > sparsity)}')

    ax.scatter(weights_reg[:, 0], weights_reg[:, 1], color = COLOR[1], alpha = 0.5, label = 'Regularized')
    for i in idx:
        drawLine(ax, weights[i, 0], weights[i, 1], weights_reg[i, 0], weights_reg[i, 1],
            color = COLOR[2], alpha = 0.5)
        radius = np.linalg.norm(weights[i] - weights_reg[i])
        drawCircle(ax, weights[i, 0], weights[i, 1], radius,
            color = COLOR[2], alpha = 0.5)

    ax.set_xlim(-5.5, 10.5)
    ax.set_ylim(-5.5, 10.5)
    ax.grid(alpha = 0.3)
    ax.legend()
    fig.savefig(plot_fname, dpi = 600, transparent = True)
    plt.clf()

if __name__ == "__main__":
    main(WEIGHTS, 'L2', 2, './fig_a.pdf', [1, 6])
    main(WEIGHTS, 'L1', 2, './fig_b.pdf', [2, 5, 9])
    main(WEIGHTS, 'Lp', 1, './fig_c.pdf', [0, 5, 9])
    main(WEIGHTS, 'L2', 5, './fig_d.pdf', [1, 6])
    main(WEIGHTS, 'L1', 5, './fig_e.pdf', [0, 5, 8])


# In this example we find a minimum of the Rosenbrock function without bounds
# on independed variables.
import numpy as np
def fun_rosenbrock(x):
    return np.array([10 * (x[1] - x[0]**2), (1 - x[0])])

# Notice that we only provide the vector of the residuals. The algorithm
# constructs the cost function as a sum of squares of the residuals, which
# gives the Rosenbrock function. The exact minimum is at ``x = [1.0, 1.0]``.

from scipy.optimize import least_squares
x0_rosenbrock = np.array([2, 2])
res_1 = least_squares(fun_rosenbrock, x0_rosenbrock)
print res_1.x
# array([ 1.,  1.])
print res_1.cost
# 2.4651903288156619e-30
print res_1.optimality
# 4.4408921315878507e-14

# We now constrain the variables, in such a way that the previous solution
# becomes infeasible. Specifically, we require that ``x[1] >= 1.5``, and
# ``x[0]`` left unconstrained. To this end, we specify the `bounds` parameter
# to `least_squares` in the form ``bounds=([-np.inf, 1.5], np.inf)``.

# We also provide the analytic Jacobian:

def jac_rosenbrock(x):
    return np.array([
        [-20 * x[0], 10],
        [-1, 0]])

# Putting this all together, we see that the new solution lies on the bound:

res_2 = least_squares(fun_rosenbrock, x0_rosenbrock, jac_rosenbrock,
                      bounds=([-np.inf, 1.5], np.inf))
print res_2.x
# array([ 1.22437075,  1.5       ])
print res_2.cost
# 0.025213093946805685
print res_2.optimality
# 1.5885401433157753e-07

# Now we solve a system of equations (i.e., the cost function should be zero
# at a minimum) for a Broyden tridiagonal vector-valued function of 100000
# variables:

def fun_broyden(x):
    f = (3 - x) * x + 1
    f[1:] -= x[:-1]
    f[:-1] -= 2 * x[1:]
    return f

# The corresponding Jacobian matrix is sparse. We tell the algorithm to
# estimate it by finite differences and provide the sparsity structure of
# Jacobian to significantly speed up this process.

from scipy.sparse import lil_matrix
def sparsity_broyden(n):
    sparsity = lil_matrix((n, n), dtype=int)
    i = np.arange(n)
    sparsity[i, i] = 1
    i = np.arange(1, n)
    sparsity[i, i - 1] = 1
    i = np.arange(n - 1)
    sparsity[i, i + 1] = 1
    return sparsity
# ...
n = 100000
x0_broyden = -np.ones(n)
# ...
res_3 = least_squares(fun_broyden, x0_broyden,
                      jac_sparsity=sparsity_broyden(n))
print res_3.cost
# 4.5687161966109073e-23
print res_3.optimality
# 1.1650454296851518e-11

# Let's also solve a curve fitting problem using robust loss function to
# take care of outliers in the data. Define the model function as
# ``y = a + b * exp(c * t)``, where t is a predictor variable, y is an
# observation and a, b, c are parameters to estimate.

# First, define the function which generates the data with noise and
# outliers, define the model parameters, and generate data:

def gen_data(t, a, b, c, noise=0, n_outliers=0, random_state=0):
    y = a + b * np.exp(t * c)
# ...
    rnd = np.random.RandomState(random_state)
    error = noise * rnd.randn(t.size)
    outliers = rnd.randint(0, t.size, n_outliers)
    error[outliers] *= 10
# ...
    return y + error
# ...
a = 0.5
b = 2.0
c = -1
t_min = 0
t_max = 10
n_points = 15
# ...
t_train = np.linspace(t_min, t_max, n_points)
y_train = gen_data(t_train, a, b, c, noise=0.1, n_outliers=3)

# Define function for computing residuals and initial estimate of
# parameters.

def fun(x, t, y):
    return x[0] + x[1] * np.exp(x[2] * t) - y
# ...
x0 = np.array([1.0, 1.0, 0.0])

# Compute a standard least-squares solution:

res_lsq = least_squares(fun, x0, args=(t_train, y_train))

# Now compute two solutions with two different robust loss functions. The
# parameter `f_scale` is set to 0.1, meaning that inlier residuals should
# not significantly exceed 0.1 (the noise level used).

res_soft_l1 = least_squares(fun, x0, loss='soft_l1', f_scale=0.1,
                            args=(t_train, y_train))
res_log = least_squares(fun, x0, loss='cauchy', f_scale=0.1,
                        args=(t_train, y_train))

# And finally plot all the curves. We see that by selecting an appropriate
# `loss`  we can get estimates close to optimal even in the presence of
# strong outliers. But keep in mind that generally it is recommended to try
# 'soft_l1' or 'huber' losses first (if at all necessary) as the other two
# options may cause difficulties in optimization process.

t_test = np.linspace(t_min, t_max, n_points * 10)
y_true = gen_data(t_test, a, b, c)
y_lsq = gen_data(t_test, *res_lsq.x)
y_soft_l1 = gen_data(t_test, *res_soft_l1.x)
y_log = gen_data(t_test, *res_log.x)
# ...
import matplotlib.pyplot as plt
plt.plot(t_train, y_train, 'o')
plt.plot(t_test, y_true, 'k', linewidth=2, label='true')
plt.plot(t_test, y_lsq, label='linear loss')
plt.plot(t_test, y_soft_l1, label='soft_l1 loss')
plt.plot(t_test, y_log, label='cauchy loss')
plt.xlabel("t")
plt.ylabel("y")
plt.legend()
plt.show()


import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import time as ti

from sklearn import datasets

def task(N,D,T):
	a=np.zeros((len(N),len(N[0])))
	if (T == "d"): #len(N)==len(D) and len(N[0])==len(D[0]) and
		for i in range(len(N)):
			for j in range(len(N[0])):
				a[i][j]=N[i][j]/D[i][j]
	elif (T == "m"):
		for i in range(len(N)):
			for j in range(len(N[0])):
				a[i][j]=N[i][j]*D[i][j]
	return a #else return zero

def mat_fac(X,K,S=7000):
	st = ti.time()
	W = np.random.rand(len(X),K)
	H = np.random.rand(K,len(X[0]))
	(s,e,ne)=(0,0,0)
	print "W",W, "\n"
	print "H", H, "\n"

	while (s<S):

		h1 = np.dot(np.transpose(W),task(X,np.dot(W,H),"d"))
		h2 = np.dot(np.transpose(W),np.ones((len(W),len(h1[0]))))
		h3 = task(h1,h2,"d")
		H = task(H,h3,"m")

		w1 = np.dot(task(X,np.dot(W,H),"d"),np.transpose(H))
		w2 = np.dot(np.ones((len(w1),len(H[0]))),np.transpose(H))
		w3 = task(w1,w2,"d")
		W = task(W,w3,"m")

		nX = np.dot(W,H)
		for i in range(len(X)):
			for j in range(len(X[i])):
				#ne = ne + pow((X[i][j]-nX[i][j]),2)
				ne = ne + (X[i][j]*np.log((X[i][j]+0.0)/(nX[i][j]+0.0))-X[i][j]+nX[i][j])
		print ne
		if np.abs(e-ne)>0.00001:
		#if np.abs(ne)>0:
			e=ne
			ne=0
		else:
			break
		s+=1
	print "step =", s
	print "time taken =", ti.time()-st
	return (W,H,nX)

iris = np.transpose(np.array(datasets.load_iris()['data'],dtype='f'))
i1 = iris
print iris, "\n"

(nW,nH,nX) = mat_fac(iris,2)
print "new W :", "\n", nW, "\n"
print "new H :", "\n", nH, "\n"
print "new Matrix :", "\n", nX, "\n"

for i in range(len(i1)):
	for j in range(len(i1[0])):
		i1[i][j] = i1[i][j]-nX[i][j]

print "Difference Matrix :", "\n", i1


import numpy as np

def init(A, b, c, rank, m):
    A_b = A[:, (m-rank):]
    A_n = A[:, :(m-rank)]

    c_b = c[:, (m-rank):]
    c_n = c[:, :(m-rank)]

    A_b_inv = np.linalg.pinv(A_b)
    b_ = A_b_inv @ b
    tmp = c_b @ A_b_inv
    ZC = tmp @ A_n - c_n

    F = tmp @ b

    # Get the Simplex Tabel
    T1 = np.vstack((A_b_inv @ A_n, ZC))
    T2 = np.vstack((A_b, np.zeros_like(ZC)))
    T3 = np.vstack((b_, F))
    T = np.hstack((T1, T2, T3))

    return T

def main(T, rank, m):
    '''

    :param T: left is non-basic and right is basic
    :param rank: the number of basic vector or variable
    :return:
    '''
    while True:
        F = T[-1, -1]
        ZC = T[-1, :(m - rank)]

        if np.max(ZC) <= 0:
            return F

        # Find the main column
        main_col = np.argmax(T[-1, :(m-rank)])
        # Find the main row
        tmp = T[:-1, -1] / T[:-1, main_col]
        index, min_v = -1, 1e10
        for i in range(tmp.shape[0]):
            if tmp[i] < min_v and tmp[i] > 0:
                index, min_v = i, tmp[i]
        main_row = index
        if main_row == -1:
            raise Exception('No solution!')
            return False

        # Update
        T[main_row, :] = T[main_row, :] / T[main_row, main_col]
        for i in range(T.shape[0]):
            if i == main_row:
                continue
            alpha = T[i, main_col] / T[main_row, main_col]
            T[i, :] = T[i, :] - alpha * T[main_row, :]
        turn = T[:, main_col]
        T[:, main_col] = T[:, (m-rank+main_row-1)]
        T[:, (m-rank+main_row-1)] = turn

    return 0

if __name__ == '__main__':
    data = np.loadtxt('data/data-1.txt')
    n, m = data.shape

    # C: row-vector
    c = data[0, :-1]
    c = c[np.newaxis, :]
    # B: col-vector
    b = data[1:n, -1]
    b = b[:, np.newaxis]
    # A: matrix
    A = data[1:n, :-1]

    rank = min(n-1, m-1)
    assert rank == n-1
    m = m-1
    T = init(A, b, c, rank, m)
    Final = main(T, rank, m)

    print('The min value of object function is ', Final)


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

# # Basic Qubit Rotation Example
#
# In this example, we show how we can use a
# simple gradient descent method to optimize
# a unitary gate for qubit rotation. The idea
# is as follows: We start in $|1 \rangle$ state
# on a Bloch Sphere and apply rotations around
# Z-Y-Z axes (in that order) using
# $R(\phi,\theta,\omega)$, which is a
# general unitary operator parameterized
# by three real parameters, $\phi$, $\theta$,
# and $\omega$. Each of these parameters represent
# the degree of rotation around x, y and z axes
# respectively to reach the target state,
# which is defined to be $|0 \rangle$ in
# this case. $R(\phi,\theta,\omega)$ has
# the following matrix representation:
#
#
# $$
# R(\phi,\theta,\omega) = RZ(\omega)RY(\theta)RZ(\phi)= \begin{bmatrix}
# e^{-i(\phi+\omega)/2}\cos(\theta/2) & -e^{i(\phi-\omega)/2}\sin(\theta/2) \\
# e^{-i(\phi-\omega)/2}\sin(\theta/2) & e^{i(\phi+\omega)/2}\cos(\theta/2)
# \end{bmatrix}
# $$

import jax.numpy as jnp
from jax import grad
from jax.random import normal, PRNGKey

import numpy as onp

from qgrad.qgrad_qutip import basis, fidelity

def rot(phi, theta, omega):
    """Returns a rotation matrix represetning
    the rotation around Z-Y-Z axis.

    Parameters:
        phi (float): rotation angle for the
            first rotation around the z-axis
        theta (float): rotation angle for
            rotation around the y-axis
        omega (float): rotation angle for the
            second rotation around the z-axis

    Returns:
        :obj:`jnp.ndarray`: array representing
            the rotation matrix

    """

    cos = jnp.cos(theta / 2)
    sin = jnp.sin(theta / 2)

    return jnp.array(
        [
            [
                jnp.exp(-0.5j * (phi + omega)) * cos,
                -(jnp.exp(0.5j * (phi - omega))) * sin,
            ],
            [jnp.exp(-0.5j * (phi - omega)) * sin, jnp.exp(0.5j * (phi + omega)) * cos],
        ]
    )

def cost(phi, theta, omega, ket):
    r"""Returns the fidelity between
    the evolved state and the target
    :math:`|0 \rangle` state.

    Parameters:
        phi (float): rotation angle for the
            first rotation around the z-axis
        theta (float): rotation angle for
            rotation around the y-axis
        omega (float): rotation angle for the
            second rotation around the z-axis
        ket (:obj:`jnp.array`): Initial ket
            to act the rotation matrix on

    Returns:
        float: fidelity between the initial and
            the evolved state under rotation
    """
    evolved = jnp.dot(rot(phi, theta, omega), ket)
    return fidelity(evolved, basis(2, 0))[0][0]

# ## Gradient Ascent Implementation
#
# Here we have our own gradient ascent
# implementation. One may use traditional
# gradient descent by subtracting fidelity
# from $1$ in the cost function.
#
# There are multiple
# parameters, like `epochs`, `alpha`, etc,
# that one might tune further in hopes of
# better convergence. For our purposes, however,
# we see that our implementation converges well
# in about $80$ crude steps.

# initialize parameters for learning
epochs = 80
alpha = 0.2  # learning rate
weights = normal(PRNGKey(0), shape=(3,))
init_ket = basis(2, 1)  # initial |1> state
der_cost = grad(cost, argnums=[0, 1, 2])
state_hist = [Qobj(onp.array(init_ket))]

for epoch in range(epochs):
    der = jnp.asarray(der_cost(*weights, init_ket))
    weights = weights + alpha * der
    state_hist.append(Qobj(onp.dot(rot(*weights), init_ket)))
    fidel = cost(*weights, init_ket)
    progress = [epoch + 1, fidel]
    if epoch % 10 == 9:
        print("Epoch: {:2f} | Fidelity: {:3f}".format(*jnp.asarray(progress)))

# ## Bloch Sphere Visualization
#
# As we see above, we started off
# with a very low fidelity
# ($\sim$ 0.29). With gradient
# descent iterations, we progressively
# achieve better fidelities via better
# parameters, $\phi$, $\theta$,
# and $\omega$. To visualize training,
# we render our states on to a Bloch sphere
# animation below.
#
# We see how our gradient based optimizer
# walks from $|1 \rangle$ (southward) and
# converges almost perfectly to the target
# state $|0 \rangle$
# (northward) as depicted in the second figure.

# Visualization
get_ipython().run_line_magic("matplotlib", "inline")
from qutip import Bloch
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.animation as animation
import matplotlib.pyplot as plt

plt.rcParams["animation.html"] = "jshtml"
fig = plt.figure()
ax = Axes3D(fig, azim=-40, elev=30)
sphere = Bloch(axes=ax)

def animate(i):
    sphere.clear()
    sphere.add_states(state_hist[i])
    sphere.make_sphere()
    return ax

def init():
    sphere.vector_color = ["b"]
    return ax

ani = animation.FuncAnimation(
    fig, animate, onp.arange(len(state_hist)), init_func=init, repeat=True
)
ani


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

# code starts here
df = pd.read_csv(path)

#probability of fico score greater than 700
p_a = df[df['fico'].astype(float)>700].shape[0]/df.shape[0]
print(p_a)

# probability of purpose == debt_consolidation
p_b = df[df['purpose'] == 'debt_consolidation'].shape[0]/df.shape[0]
print(p_b)

#create a new data frame for condition['purpose'] == debt_consolidation
df1 = df[df['purpose']=='debt_consolidation']

#Calculate the P(A|B)
p_a_b = df1[df1['fico'].astype(float)>700].shape[0]/df1.shape[0]
print(p_a_b)

#Check whether P(A) and P(B) are independent from each other
result = (p_a == p_a_b)
print(result)
# code ends here

# --------------
# code starts here

#calculate p(A) for the event that paid.back.loan == Yes and store it in a variable prob_1p
prob_lp = df[df['paid.back.loan']=="Yes"].shape[0]/df.shape[0]
print(prob_lp)

#calculate the probability for the event credit.policy ==Yes and store it in a varaible prob_cs
prob_cs = df[df['credit.policy']=="Yes"].shape[0]/df.shape[0]
print(prob_cs)

#set a new data frame
new_df = df[df['paid.back.loan']=="Yes"]

#calcualte p(B|A) for the event paid.back.loan and credit.policy == "Yes"
prob_pd_cs =  new_df[new_df["credit.policy"]=="Yes"].shape[0]/new_df.shape[0]
print(prob_pd_cs)

#calculate the condionaltiy probabitliy using the bayes theorem
bayes = ((prob_pd_cs)*(prob_lp))/prob_cs
print(bayes)
# code ends here

# --------------
# code starts here

df.purpose.value_counts(normalize=True).plot(kind='bar')
df1 = df[df['paid.back.loan']=='No']
df1.purpose.value_counts(normalize=True).plot(kind='bar')
# code ends here

# --------------
# code starts here
inst_median = df['installment'].median()
print("The value of the median of installment",inst_median)
inst_mean = df["installment"].mean()
print("The value of the mean of the installment",inst_mean)
df.hist(column='installment',bins = 8)
df.hist(column='log.annual.inc',bins = 8)

# code ends here


import numpy as np

class Perceptron(object):
    """Implements a perceptron network"""
    def __init__(self, input_size, lr=1, epochs=100):
        self.W = np.zeros(input_size+1)
        # add one for bias
        self.epochs = epochs
        self.lr = lr

   #activation function
    def activation_fn(self, x):
        #return (x >= 0).astype(np.float32)
        return 1 if x >= 0 else 0

 #we need a prediction function to run an input through the perceptron and return an output.
    def predict(self, x):
        z = self.W.T.dot(x)
        a = self.activation_fn(z)
        return a

    def fit(self, X, d):
        for _ in range(self.epochs):
            for i in range(d.shape[0]):
                x = np.insert(X[i], 0, 1)
                y = self.predict(x)
                e = d[i] - y
                self.W = self.W + self.lr * e * x
#the easiset set of data that we can provide is the AND gate. Given is set of inputs and outputs.
if __name__ == '__main__':
    X = np.array([
        [0, 0],
        [0, 1],
        [1, 0],
        [1, 1]
    ])
    d = np.array([0, 0, 0, 1])

    perceptron = Perceptron(input_size=2)
    perceptron.fit(X, d)
    print(perceptron.W)


import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_classification
import seaborn as sns

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

def compute_cost(X, y ,theta):
    m = len(y)
    h = sigmoid(X @ theta)
    epsilon = 1e-5
    cost = (1/m)*(((-y).T @ np.log(h + epsilon))-((1-y).T @ np.log(1-h + epsilon)))
    return cost

def gradient_descent(X, y, params, learning_rate, iterations):
    m = len(y)
    cost_history = np.zeros((iterations,1))

    for i in range(iterations):
        params = params - (learning_rate/m) * (X.T @ (sigmoid(X @ params) - y))
        cost_history[i] = compute_cost(X, y, params)

    return (cost_history, params)

def predict(X, params):
    return np.round(sigmoid(X @ params))

X, y = make_classification(n_samples=500, n_features=2, n_redundant=0, n_informative=1,
                             n_clusters_per_class=1, random_state=14)

y = y[:,np.newaxis]

sns.set_style('white')
sns.scatterplot(X[:,0],X[:,1],hue=y.reshape(-1));

m = len(y)

X = np.hstack((np.ones((m,1)),X))
n = np.size(X,1)
params = np.zeros((n,1))

iterations = 1500
learning_rate = 0.03

initial_cost = compute_cost(X, y, params)

print("Initial Cost is: {} \n".format(initial_cost))

(cost_history, params_optimal) = gradient_descent(X, y, params, learning_rate, iterations)

print("Optimal Parameters are: \n", params_optimal, "\n")

plt.figure()
sns.set_style('white')
plt.plot(range(len(cost_history)), cost_history, 'r')
plt.title("Convergence Graph of Cost Function")
plt.xlabel("Number of Iterations")
plt.ylabel("Cost")
plt.show()

y_pred = predict(X, params_optimal)
score = float(sum(y_pred == y))/ float(len(y))

print(score)

slope = -(params_optimal[1] / params_optimal[2])
intercept = -(params_optimal[0] / params_optimal[2])

sns.set_style('white')
sns.scatterplot(X[:,1],X[:,2],hue=y.reshape(-1));

ax = plt.gca()
ax.autoscale(False)
x_vals = np.array(ax.get_xlim())
y_vals = intercept + (slope * x_vals)
plt.plot(x_vals, y_vals, c="k");


import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import scipy.stats as stats
from scipy.integrate import quad
from scipy.fft import fft, ifft
from scipy.interpolate import interp1d
from functools import partial
from scipy.optimize import minimize, fsolve, newton
import matplotlib.pyplot as plt

class StochasticProcesses:
    def __init__(self, option_type='call'):
        self.option_type = option_type

    def geometric_BM(self, T, s0, mu, sigma, n):
        x = np.zeros(n + 1)
        s = np.zeros(n + 1)
        time = np.zeros(n + 1)

        x[0] = np.log(s0)
        dt = T/float(n)

        for t in range(n):
            x[t+1] = x[t] + (mu - (sigma**2)/2) * dt + sigma * np.sqrt(dt) * stats.norm.rvs(loc=0, scale=1)
            time[t+1] = time[t] + dt

        s = np.exp(x)

        return time, s

    def poisson_process(self, T, s0, xiP, n, type_p='ordinary'):
        time = np.zeros(n + 1)
        dt = T/float(n)
        poisson_distr = np.random.poisson(xiP * dt, n + 1)

        if type_p == 'ordinary':
            x = np.zeros(n + 1)
            x[0] = s0

            for t in range(n):
                x[t+1] = x[t] + poisson_distr[t]
                time[t+1] = time[t] + dt

            return time, x

        elif type_p == 'compensated':
            xc = np.zeros(n + 1)
            xc[0] = s0

            for t in range(n):
                xc[t+1] = xc[t] + poisson_distr[t] - xiP * dt
                time[t+1] = time[t] + dt

            return time, xc
        else:
            print('Wrong type process, available: ordinary and compensated')

    def merton_process(self, T, s0, xiP, muj, sigmaj, r, sigma, n):
        time = np.zeros(n + 1)
        dt = T/float(n)

        z = np.random.normal(0.0, 1.0, n + 1)
        zj = np.random.normal(muj, sigmaj, n + 1)
        poisson_distr = np.random.poisson(xiP * dt, n + 1)

        x = np.zeros(n + 1)
        s = np.zeros(n + 1)

        s[0] = s0
        x[0] = np.log(s0)

        EeJ = np.exp(muj + 0.5 * sigmaj**2)

        for t in range(n):
            x[t+1] = x[t] + (r - xiP * (EeJ - 1) - 0.5 * sigma**2) * dt +\
                sigma * np.sqrt(dt) * z[t] + zj[t] * poisson_distr[t]

            time[t+1] = time[t] + dt

        s = np.exp(x)

        return time, s

    def plot_path(self, time, s, label='Process path', title='Process Visualization'):
        plt.subplots(figsize=(10, 5), dpi=100)
        plt.plot(time, s, label=label)

        plt.title(title, fontsize=16)
        plt.xlabel('Time', fontsize=14)
        plt.ylabel('Values', fontsize=14)
        plt.legend()
        plt.show()


import numpy as np
import sklearn.datasets as skdata
from sklearn.linear_model import LinearRegression

boston_housing_data = skdata.load_boston()
x = boston_housing_data.data
y = boston_housing_data.target

print(x.shape) #506, 13
print(y.shape) #506,

#Split the data 90 percent for training, 10 percent for testing
split_idx = int(0.90*x.shape[0])
x_train,y_train = x[:split_idx, :], y[:split_idx]
x_test, y_test = x[split_idx:, :], y[split_idx:]

#Sets up our Linear Regression Model
model = LinearRegression()

#Trains our regression model
model.fit(x_train, y_train)

#Make predictions
predictions = model.predict(x_test)

print("predictions are", predictions)

#meaduring regression error
def mean_squared_error(y_hat, y):
    #y_hat is your predictions
    return np.mean((y_hat-y)**2)

mse = mean_squared_error(predictions, y_test)

print("mse is", mse) #should be around 10.8~

#LINEAR REGRESSION VIA NORMAL EQUATION
class LinearRegressionNormalEqn(object):

    def __init__(self):
        self.weights = None

    def  fit(self, x, y):
        x_transpose_x_inv = np.linalg.inv(np.matmul(x.T, x)) # x.T == np.transpose(x)
        self.weights = np.matmul(np.matmul(x_transpose_x_inv, x.T), y)
        #xTx = np.matmul(np.transpose(x), x)
        #xTx_inv = np.inv(xTx)
        #self.weights = np.matmul(np.matmul(xTx_inv, np.transpose(x), y))

    def predict(self, x):
        return np.matmul(x, self.weights)

#Sets up our Linear Regression model
model_norm_eqn = LinearRegressionNormalEqn()

#Trains our regression model
model_norm_eqn.fit(x_train, y_train)

#Make predictions
predictions_norm_eqn = model_norm_eqn.predict(x_test)

#Evaluate our model
mse_norm_eqn = mean_squared_error(predictions_norm_eqn, y_test) #Should be around 13

print("mse norm eqn is ", mse_norm_eqn)

class LinearRegressionSVD(object):

    def __init__(self):
        self.weights = None

    def fit(self, x, y):
        U, S, V_t = np.linalg.svd(x)
        padding = np.zeros([x.shape[0] -S.shape[0], S.shape[0]])
        S_pseudo = np.concatenate([np.diag(1.0/S), padding], axis =0).T
        X_pseudo = np.matmul(np.matmul(V_t.T, S_pseudo), U.T)
        self.weights = np.matmul(X_pseudo, y)

    def predict(self, x):
        return np.matmul(x, self.weights)

#Split the data 90 percent for training, 10 percent for testing
split_idx = int(0.90*x.shape[0])
x_train, y_train = x[:split_idx, :], y[:split_idx]
x_test, y_test = x[split_idx:, :], y[split_idx:]
#if N < d, issues, too huge... use pseudo inverse//less dangerous

#Sets up our Linear Regression model
model_svd = LinearRegressionSVD()

#Trains our regression model
model_svd.fit(x_train, y_train)

#Make predictions
predictions_svd = model_svd.predict(x_test)

#Evaluate our model
mse_svd = mean_squared_error(predictions_svd, y_test)

print("mse svd", mse_svd)


from kernel_exp_family.kernels.kernels import gaussian_kernel
import numpy as np

def compute_b_sym(Z, K, sigma):
    assert K.shape[0] == Z.shape[0]
    assert K.shape[0] == K.shape[1]

    D = Z.shape[1]
    N = Z.shape[0]

    b = np.zeros(N)
    K1 = np.sum(K, 1)
    for l in np.arange(D):
        x_l = Z[:, l]
        s_l = x_l ** 2

        # Replaces dot product with np.diag via broadcasting
        # See http://mail.scipy.org/pipermail/numpy-discussion/2007-March/026809.html
        D_s_K = s_l[:, np.newaxis] * K
        D_x_K = x_l[:, np.newaxis] * K

        b += 2. / sigma * (K.dot(s_l) \
                        + np.sum(D_s_K, 1) \
                        - 2 * D_x_K.dot(x_l)) - K1
    return b

def compute_C_sym(Z, K, sigma):
    assert K.shape[0] == Z.shape[0]
    assert K.shape[0] == K.shape[1]

    D = Z.shape[1]
    N = Z.shape[0]

    C = np.zeros((N, N))
    for l in np.arange(D):
        x_l = Z[:, l]

        # Replaces dot product with np.diag via broadcasting
        # See http://mail.scipy.org/pipermail/numpy-discussion/2007-March/026809.html
        D_x_K = x_l[:, np.newaxis] * K
        K_D_x = K * x_l

        C += (D_x_K - K_D_x).dot(K_D_x - D_x_K)

    return C

def fit_sym(Z, sigma, lmbda, K=None, b=None, C=None):
        # compute quantities
        if K is None:
            K = gaussian_kernel(Z, sigma=sigma)

        if b is None:
            b = compute_b_sym(Z, K, sigma)

        if C is None:
            C = compute_C_sym(Z, K, sigma)

        # solve regularised linear system
        a = -sigma / 2. * np.linalg.solve(C + (K + np.eye(len(C))) * lmbda,
                                          b)

        return a

def objective_sym(Z, sigma, lmbda, alpha, K=None, b=None, C=None):
    if K is None and ((b is None or C is None) or lmbda > 0):
        K = gaussian_kernel(Z, sigma=sigma)

    if C is None:
        C = compute_C_sym(Z, K, sigma)

    if b is None:
        b = compute_b_sym(Z, K, sigma)

    N = len(Z)
    first = 2. / (N * sigma) * alpha.dot(b)
    second = 2. / (N * sigma ** 2) * alpha.dot(
                                               (C + (K + np.eye(len(C))) * lmbda).dot(alpha)
                                               )
    J = first + second
    return J


# Polynomial Regression code for github

# Importing the libraries
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

# Importing the dataset
dataset = pd.read_csv('../Datasets/HeightVsAge.csv')
ind = dataset.iloc[:,0].values #independent variable
ind = ind.reshape(len(ind),1)  #reshaping the independent variables to match the dimensions for fitting
dep = dataset.iloc[:, 1].values #dependent variable

# Splitting the dataset into the Training set and Test set
from sklearn.model_selection import train_test_split
ind_train, ind_test, dep_train, dep_test = train_test_split(ind, dep, test_size = 0.2, random_state = 0)

# Fitting Polynomial Regression to the dataset
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import PolynomialFeatures
poly_reg = PolynomialFeatures(degree = 3)  # you can change the degree of polynomial here
ind_poly = poly_reg.fit_transform(ind_train)
poly_reg.fit(ind_poly, dep)
lin_reg_2 = LinearRegression()
lin_reg_2.fit(ind_poly, dep_train)

# Visualising the Polynomial Regression Training set results
#Here we do not use the method that we used previously,because here we have a curve and is we use the previous methond,we will not get a smooth curve
X_grid = np.arange(min(ind), max(ind), 0.1)
X_grid = X_grid.reshape((len(X_grid), 1))
plt.scatter(ind_train, dep_train, color = 'red')
plt.plot(X_grid, lin_reg_2.predict(poly_reg.fit_transform(X_grid)), color = 'blue')
plt.title('Training Set Results')
plt.xlabel('Age')
plt.ylabel('Height')
plt.show()

# Visualising the Polynomial Regression Test Set results
X_grid = np.arange(min(ind), max(ind), 0.1)
X_grid = X_grid.reshape((len(X_grid), 1))
plt.scatter(ind_test, dep_test, color = 'red')
plt.plot(X_grid, lin_reg_2.predict(poly_reg.fit_transform(X_grid)), color = 'blue')
plt.title('Test Set Results')
plt.xlabel('Age')
plt.ylabel('Height')
plt.show()


#!/usr/bin/env python
'''

File : 		StarTrailMovementv2.py
Author : 	Greg Furlich
Date Created : 	01/06/2018
Copyright : 	(c) 2018, Greg Furlich
License :	MIT License

Purpose : A python script simulate star trails for a random array of positions for <n_stars> around a randomly positioned rotational axis. The stars are then rotated for a length of a <rotation_angle>. A gif is created using the animation tools in matplotlib.

Execution : ./StarTrailMovementv2.py <n_stars> <rotation_angle>

Example Execution : ./StarTrailMovementv2.py 200 30

Animation based on : rain.py by Nicolas P. Rougier (https://matplotlib.org/examples/animation/rain.html)

'''

#--- Start of Script ---#

#--- Importing Python Modules ---#

import sys
import numpy as np
import math
import time
import os, errno
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from matplotlib import animation
from matplotlib.colors import hsv_to_rgb

#--- Initial Parameters ---#

t_start = time.time()

# date generated :
#date = time.strftime('v%Y%m%d_%H%M%S')	# with sec percision
date = time.strftime('v%Y%m%d') # with day percision

pi = 3.14159265359

# Defining Rectangular window for plot :
# 16:9 aspect ratio

w = 16.		# width
h = 9.		# height

# Number of Stars :
n_stars = int(sys.argv[1])

# Angle of Rotation (in Radians):
rotation_angle = float(sys.argv[2]) * pi / 180

# Angle Steps :
delta_angle = 1
delta_angle = delta_angle * pi / 180	# convert to radians

# Steps of Rotation :
n_rotations = int(rotation_angle / delta_angle)

#--- Star Initial Positions ---#

# Initialize Star Data Arrays :
stars = np.zeros(n_stars, dtype=[('position', float, 2),
	('component', 	float, 2),
	('radial', 	float, 1),
	('angle', 	float, 1),
	('size',     	float, 1),
	('alpha',    	float, 1),
	('color',    	float, 3)])

#hsv = np.zeros( (n_stars,3))

# Rotational Axis :
rotational_axis_x = np.random.uniform(0, w)
rotational_axis_y = np.random.uniform(0, h)

#print rotational_axis_x, rotational_axis_y

# Find max radius from rotational axis to corners

def radialDistance(x1,y1,x2,y2):
	'''
	Function for determining the radial distance between two points using pythagreons theorem.
	'''
	r = math.sqrt( math.pow(x2 - x1, 2) + math.pow(y2 - y1, 2) )
	return r ;

r1 = radialDistance( 0,  0, rotational_axis_x, rotational_axis_y)
r2 = radialDistance( 0,  w, rotational_axis_x, rotational_axis_y)
r3 = radialDistance( h,  0, rotational_axis_x, rotational_axis_y)
r4 = radialDistance( h,  w, rotational_axis_x, rotational_axis_y)

r = [r1, r2, r3, r4]

r.sort()

r_max = r[-1]

# Stars Random Positions :
stars['position'][:,0] = np.random.uniform(rotational_axis_x - r_max, rotational_axis_x + r_max, n_stars)
stars['position'][:,1] = np.random.uniform(rotational_axis_y - r_max, rotational_axis_y + r_max, n_stars)

# Initial Configuration from Rotational Axis :
stars['component'][:,0] = stars['position'][:,0] - rotational_axis_x
stars['component'][:,1] = stars['position'][:,1] - rotational_axis_y

stars['radial'] = np.power( np.power( stars['component'][:,0] ,2 ) + np.power( stars['component'][:,1] ,2 ) , .5)

stars['angle'] = np.arctan( stars['component'][:,0] / stars['component'][:,1])

#--- Star Characteristics ---#

# Star Alpha (Transparency) :
# Beta Distribution Sampling
# (0 - 1 skewed distribution towards 0):
stars['alpha'] = 1 - np.random.beta(2,15)

# Star Size :
stars['size'] = np.random.beta(2,4)

# Star Random Color Variation from White :
# White in HSV (0,0,1)

# Add Normal Colored Stars
hsv = np.random.uniform(0, 1, (n_stars, 3) ) 	# Hue

# Convert HSV to RGB
stars['color'] = hsv_to_rgb( hsv )

#h = np.random.uniform(0, 1) 		# Hue
#s = np.random.beta(1, 15)		# Saturation
#v = 1 - np.random.beta(1, 15)	# Value

#--- Plot Initial Star and Rotational Positions ---#

stars_initial = plt.figure(1)		# Initialize First Plot

# Legend Labes :
star_label = 'n_stars = '+str(n_stars)
rotation_label = 'Axis of Rotation, rotate = '+str(sys.argv[2])

# Scatter Plots :
plt.scatter( stars['position'][:, 0], stars['position'][:, 1], marker='*', label = star_label)	# Star Plot
plt.scatter(rotational_axis_x, rotational_axis_y, marker='o', label = rotation_label)			# Rotation Axis Plot

# Plot Limits :
plt.xlim([0, w])		# X Range
plt.ylim([0, h])		# Y Range

# Legend :
plt.legend(loc='upper left')

print "Rendering Initial Figure : Figures/Stars_Initial_"+date+".png"

# Save Plot :
plt.savefig("Figures/Stars_Initial_"+date+".png")

#--- Star Rotation Scatter plot ---#
# Updated during animation as the stars rotate

star_trails = plt.figure(2)

# Plot Limits :
plt.xlim([0, w])		# X Range
plt.ylim([0, h])		# Y Range

# Remove Plot Frame and Axes :
ax = star_trails.gca()
#ax.set_frame_on(False)
#ax.set_aspect('equal')	# Set equal aspect ratio
#ax.set_xticks([])
#ax.set_yticks([])
#plt.axis('off')

# Save Figure Title :
out_dir = "Gif_Figures/Star_Trail_Movement_%s/" % (date,)

# Background colors for the sky:
background_color = '#000814'

# Create Directory for Out Figures :
try:
	os.makedirs(out_dir)
except OSError as e:
	if e.errno != errno.EEXIST:
		raise

star_scat = ax.scatter(stars['position'][:, 0], stars['position'][:, 1], s=stars['size'], lw=0.5, edgecolors = stars['color'], facecolors = stars['color'])

#--- Update Star Trail Rotation Function ---#
def update_star_trail(i_rotation):

	# Rotate Stars Position :
	stars['position'][:,0] = rotational_axis_x + stars['radial'] * np.cos( stars['angle'] + i_rotation * np.pi / 180 )
	stars['position'][:,1] = rotational_axis_y + stars['radial'] * np.sin( stars['angle'] + i_rotation * np.pi / 180 )

	# Update Star Position on Scatter Plot :
	star_scat.set_offsets(stars['position'])

	#print stars['position'][1,0], stars['position'][1,1]

	# Save Figure Title :
	#out_fig = out_dir+"Star_Trails_%04d.png" % (i_rotation,)

	# Save Plot w/ Colored Background :
	#star_trails.savefig(out_fig, dpi=500, facecolor = background_color, bbox_inches='tight', pad_inches=0)

	#print '\rRendering Rotation {:04d} / {:d} '.format(i_rotation, n_rotations)

#--- Create Star Trail Animation ---#

# Star Trail Animation
# using the update function as the animation director.
star_anim = animation.FuncAnimation(star_trails, update_star_trail, frames = n_rotations)

#--- Create GIF ---#

# Define GIF Name :
out_gif = 'GIFs/Star_Trail_Movement_%s.gif' % (date)

print 'Rendering GIF : '+out_gif

# Save Animation as GIF :
star_anim.save( out_gif, writer='imagemagick', fps=20)

# GIF Size :
os.system('du -sh '+out_gif)

#--- Time Elapsed ---#

# Total time elapsed :
t_total = time.time() - t_start

print 'total time : %f secs' % (t_total)

#--- End of Script ---#


#-------------------------------------------------------------------------------
# Name:        Linear Regression
# Purpose:
#
# Author:      Nonlining
#
# Created:     05/01/2017
# Copyright:   (c) Nonlining 2017
# Licence:     <your licence>
#-------------------------------------------------------------------------------
import numpy as np
from math import log

def get_residual_sum_of_squares(features_matrix, weights, outputs):
    pred_y = predict(features_matrix, weights)
    Residual = outputs - pred_y
    RSS = (Residual*Residual).sum()
    return(RSS)

def extract_data_from_features(data, features, output):
    data['constant'] = 1.0
    features = ['constant'] + features
    features_matrix = np.array(data[features])

    if output != None:
        output_array = np.array(data[output])
    else:
        output_array = []

    return(features_matrix, output_array)

def predict(feature_matrix, weights):
    return np.dot(feature_matrix, weights)

def regression_gradient_descent(feature_matrix, output, initial_weights, step_size, tolerance):
    converged = False
    weights = np.array(initial_weights)
    #count = 0

    while not converged:
        predictions = predict(feature_matrix, weights)
        errors =  output - predictions
        partial =  -2*np.dot(feature_matrix.T, errors)
        weights = weights - step_size*partial
        gradient_magnitude = np.sqrt(np.sum(partial*partial))
        #count = count + 1
        #if (count%10000 == 0):
        #    print gradient_magnitude

        if gradient_magnitude < tolerance:
            converged = True

    return(weights)


import numpy as np
from scipy.optimize import minimize

LOSS_TYPES = ['l1', 'median', 'mae', 'l2', 'mse', 'quantile', 'q']

def _residual_loss_fn(x, y, w, loss_type, quantile):
    res = y - x @ w
    if loss_type.lower() in ['l2', 'mse']:
        loss_ = np.mean(res ** 2) / 2
        d_loss_ = - x.T @ res / res.shape[0]
    elif loss_type.lower() in ['l1', 'median', 'mae']:
        loss_ = np.abs(res).mean()
        d_loss_ = - x.T @ np.sign(res) / res.shape[0]
    elif loss_type.lower() in ['quantile', 'q']:
        quantiles = np.where(res < 0, quantile - 1, quantile)
        loss_ = (quantiles * res).mean()
        d_loss_ = - x.T @ quantiles / res.shape[0]
    else:
        raise ValueError(f'Unknown loss_type=`{quantile}`!')
    return loss_, d_loss_

def _regularization_loss(w, l1_w, l2_w):
    loss_ = 0.0
    d_loss_ = np.zeros_like(w)
    if l1_w > 0.0:
        loss_ += l1_w * np.abs(w).sum()
        d_loss_ += l1_w * np.sign(w)
    if l2_w > 0.0:
        loss_ += l2_w * (w ** 2).sum() / 2
        d_loss_ += l2_w * w
    return loss_, d_loss_

def scale_std(x, scale=True):
    """ Scale data by its standard deviation. """
    if scale is True:
        x_std = x.std(axis=0) + 1e-12
        x /= x_std
    else:
        x_std = np.ones(x.shape[1])
    return x, x_std

def check_and_prepare(x, y, loss_type, quantile, scale, fit_bias, copy_xy):
    """ Check in puts and reshape data to 2d. """
    assert loss_type.lower() in LOSS_TYPES, \
        f'Expected loss_type in {LOSS_TYPES}. Got: loss_type={loss_type}!'
    if loss_type == 'quantile':
        assert quantile is not None and 0.0 < quantile < 1.0, \
            f'Expected 0.0 < quantile < 1.0. Got: quantile={quantile}!'
    assert x.shape[0] == y.shape[0], f'{x.shape[0]} != {y.shape[0]}'
    assert x.ndim == 2
    if copy_xy is True:
        x = x.copy()
        y = y.copy()
    if y.ndim == 1:
        y = y[:, None]
    else:
        assert y.ndim == 2
    # Scale data and optionally adjust for bias term:
    x, x_std = scale_std(x, scale=scale)
    y, y_std = scale_std(y, scale=scale)
    if fit_bias is True:
        x = np.hstack((x, np.ones((x.shape[0], 1))))
    return x, x_std, y, y_std

def lbfgs_fit(loss_fn, w_init, grad=True):
    """ Simple wrapper for L-BFGS scipy routine. """
    original_shape = w_init.shape
    w_init = w_init.ravel()
    w_star = minimize(fun=loss_fn, x0=w_init, method='L-BFGS-B', jac=grad).x
    w_star = w_star.reshape(original_shape)
    return w_star

def postprocess_parameters(w_star, x_std, y_std, fit_bias, clip_weights):
    """ Adjust bias terms, weight clipping and re-scaling of weights. """
    if fit_bias is True:
        bias = y_std * w_star[-1, :]
        w_star = w_star[:-1, :]
    else:
        bias = np.zeros(w_star.shape[1])
    if clip_weights > 0.0:
        w_max = np.abs(w_star).max()
        w_star[np.abs(w_star) < w_max * clip_weights] = 0.0
    w_orig = w_star * y_std / x_std[:, None]
    return w_orig, w_star, bias


# 2020.02.09
# Sorry for being away for 2 weeks. Was not really in the mood. Also I was trying to work on something else, which doesn't seem to be promising :-(
# Problem Statement:
# https://leetcode.com/problems/triangle/

import numpy as np
class Solution:
    # Solution 1: more concise, a bit faster
    def minimumTotal(self, triangle: List[List[int]]) -> int:
        if len(triangle) == 0: return 0
        dp_structure = np.zeros((len(triangle), len(triangle[-1])))
        # from bottom to up
        for i in range(0, len(triangle)):
            for j in range(0, len(triangle)-i):
                if i == 0:
                    dp_structure[len(triangle)-1-i][j] = triangle[len(triangle)-1-i][j]
                else:
                    dp_structure[len(triangle)-1-i][j] = triangle[len(triangle)-1-i][j] + \
                    min(dp_structure[len(triangle)-i][j], dp_structure[len(triangle)-i][j+1])
        return int(dp_structure[0][0])

    # Solution 2: the first one I came up with, a bit slower
    def minimumTotal(self, triangle: List[List[int]]) -> int:
        if len(triangle) == 0: return 0

        # initialize dp structure
        self.dp_structure = np.zeros((len(triangle), len(triangle[-1])))
        for i in range(0, len(triangle)):
            for j in range(0, len(triangle[-1])):
                self.dp_structure[i][j] = inf

        return int(self.minimumTotalHelper(triangle, 0))

    def minimumTotalHelper(self, triangle, index):
        # check if already calculated
        if self.dp_structure[len(triangle)-1][index] != inf:
            return self.dp_structure[len(triangle)-1][index]
        else:
            # check if already reached the bottom
            if len(triangle) == 1:
                if len(triangle[0]) == 1:
                    return triangle[0][0]
                else:
                    return min(triangle[0][index], triangle[0][index]+1)

            temp = min(self.minimumTotalHelper(triangle[1:], index), \
                       self.minimumTotalHelper(triangle[1:], index+1))

            sum = triangle[0][index] + temp
            # store in the dp structure
            self.dp_structure[len(triangle)-1][index] = sum
            return sum


from sympy.core.numbers import (I, Rational)
from sympy.core.singleton import S
from sympy.core.symbol import (Dummy, symbols)
from sympy.functions.elementary.exponential import log
from sympy.functions.elementary.miscellaneous import sqrt
from sympy.functions.elementary.trigonometric import atan
from sympy.integrals.integrals import integrate
from sympy.polys.polytools import Poly
from sympy.simplify.simplify import simplify

from sympy.integrals.rationaltools import ratint, ratint_logpart, log_to_atan

from sympy.abc import a, b, x, t

half = S.Half

def test_ratint():
    assert ratint(S.Zero, x) == 0
    assert ratint(S(7), x) == 7*x

    assert ratint(x, x) == x**2/2
    assert ratint(2*x, x) == x**2
    assert ratint(-2*x, x) == -x**2

    assert ratint(8*x**7 + 2*x + 1, x) == x**8 + x**2 + x

    f = S.One
    g = x + 1

    assert ratint(f / g, x) == log(x + 1)
    assert ratint((f, g), x) == log(x + 1)

    f = x**3 - x
    g = x - 1

    assert ratint(f/g, x) == x**3/3 + x**2/2

    f = x
    g = (x - a)*(x + a)

    assert ratint(f/g, x) == log(x**2 - a**2)/2

    f = S.One
    g = x**2 + 1

    assert ratint(f/g, x, real=None) == atan(x)
    assert ratint(f/g, x, real=True) == atan(x)

    assert ratint(f/g, x, real=False) == I*log(x + I)/2 - I*log(x - I)/2

    f = S(36)
    g = x**5 - 2*x**4 - 2*x**3 + 4*x**2 + x - 2

    assert ratint(f/g, x) == \
        -4*log(x + 1) + 4*log(x - 2) + (12*x + 6)/(x**2 - 1)

    f = x**4 - 3*x**2 + 6
    g = x**6 - 5*x**4 + 5*x**2 + 4

    assert ratint(f/g, x) == \
        atan(x) + atan(x**3) + atan(x/2 - Rational(3, 2)*x**3 + S.Half*x**5)

    f = x**7 - 24*x**4 - 4*x**2 + 8*x - 8
    g = x**8 + 6*x**6 + 12*x**4 + 8*x**2

    assert ratint(f/g, x) == \
        (4 + 6*x + 8*x**2 + 3*x**3)/(4*x + 4*x**3 + x**5) + log(x)

    assert ratint((x**3*f)/(x*g), x) == \
        -(12 - 16*x + 6*x**2 - 14*x**3)/(4 + 4*x**2 + x**4) - \
        5*sqrt(2)*atan(x*sqrt(2)/2) + S.Half*x**2 - 3*log(2 + x**2)

    f = x**5 - x**4 + 4*x**3 + x**2 - x + 5
    g = x**4 - 2*x**3 + 5*x**2 - 4*x + 4

    assert ratint(f/g, x) == \
        x + S.Half*x**2 + S.Half*log(2 - x + x**2) + (9 - 4*x)/(7*x**2 - 7*x + 14) + \
        13*sqrt(7)*atan(Rational(-1, 7)*sqrt(7) + 2*x*sqrt(7)/7)/49

    assert ratint(1/(x**2 + x + 1), x) == \
        2*sqrt(3)*atan(sqrt(3)/3 + 2*x*sqrt(3)/3)/3

    assert ratint(1/(x**3 + 1), x) == \
        -log(1 - x + x**2)/6 + log(1 + x)/3 + sqrt(3)*atan(-sqrt(3)
             /3 + 2*x*sqrt(3)/3)/3

    assert ratint(1/(x**2 + x + 1), x, real=False) == \
        -I*3**half*log(half + x - half*I*3**half)/3 + \
        I*3**half*log(half + x + half*I*3**half)/3

    assert ratint(1/(x**3 + 1), x, real=False) == log(1 + x)/3 + \
        (Rational(-1, 6) + I*3**half/6)*log(-half + x + I*3**half/2) + \
        (Rational(-1, 6) - I*3**half/6)*log(-half + x - I*3**half/2)

    # issue 4991
    assert ratint(1/(x*(a + b*x)**3), x) == \
        (3*a + 2*b*x)/(2*a**4 + 4*a**3*b*x + 2*a**2*b**2*x**2) + (
            log(x) - log(a/b + x))/a**3

    assert ratint(x/(1 - x**2), x) == -log(x**2 - 1)/2
    assert ratint(-x/(1 - x**2), x) == log(x**2 - 1)/2

    assert ratint((x/4 - 4/(1 - x)).diff(x), x) == x/4 + 4/(x - 1)

    ans = atan(x)
    assert ratint(1/(x**2 + 1), x, symbol=x) == ans
    assert ratint(1/(x**2 + 1), x, symbol='x') == ans
    assert ratint(1/(x**2 + 1), x, symbol=a) == ans
    # this asserts that as_dummy must return a unique symbol
    # even if the symbol is already a Dummy
    d = Dummy()
    assert ratint(1/(d**2 + 1), d, symbol=d) == atan(d)

def test_ratint_logpart():
    assert ratint_logpart(x, x**2 - 9, x, t) == \
        [(Poly(x**2 - 9, x), Poly(-2*t + 1, t))]
    assert ratint_logpart(x**2, x**3 - 5, x, t) == \
        [(Poly(x**3 - 5, x), Poly(-3*t + 1, t))]

def test_issue_5414():
    assert ratint(1/(x**2 + 16), x) == atan(x/4)/4

def test_issue_5249():
    assert ratint(
        1/(x**2 + a**2), x) == (-I*log(-I*a + x)/2 + I*log(I*a + x)/2)/a

def test_issue_5817():
    a, b, c = symbols('a,b,c', positive=True)

    assert simplify(ratint(a/(b*c*x**2 + a**2 + b*a), x)) == \
        sqrt(a)*atan(sqrt(
            b)*sqrt(c)*x/(sqrt(a)*sqrt(a + b)))/(sqrt(b)*sqrt(c)*sqrt(a + b))

def test_issue_5981():
    u = symbols('u')
    assert integrate(1/(u**2 + 1)) == atan(u)

def test_issue_10488():
    a,b,c,x = symbols('a b c x', positive=True)
    assert integrate(x/(a*x+b),x) == x/a - b*log(a*x + b)/a**2

def test_issues_8246_12050_13501_14080():
    a = symbols('a', nonzero=True)
    assert integrate(a/(x**2 + a**2), x) == atan(x/a)
    assert integrate(1/(x**2 + a**2), x) == atan(x/a)/a
    assert integrate(1/(1 + a**2*x**2), x) == atan(a*x)/a

def test_issue_6308():
    k, a0 = symbols('k a0', real=True)
    assert integrate((x**2 + 1 - k**2)/(x**2 + 1 + a0**2), x) == \
        x - (a0**2 + k**2)*atan(x/sqrt(a0**2 + 1))/sqrt(a0**2 + 1)

def test_issue_5907():
    a = symbols('a', nonzero=True)
    assert integrate(1/(x**2 + a**2)**2, x) == \
         x/(2*a**4 + 2*a**2*x**2) + atan(x/a)/(2*a**3)

def test_log_to_atan():
    f, g = (Poly(x + S.Half, x, domain='QQ'), Poly(sqrt(3)/2, x, domain='EX'))
    fg_ans = 2*atan(2*sqrt(3)*x/3 + sqrt(3)/3)
    assert log_to_atan(f, g) == fg_ans
    assert log_to_atan(g, f) == -fg_ans


#!/usr/bin/env python3
# -*- encoding: utf-8 -*-
#Description: Probability of antibodies after vaccination
#Please note: For entertainment only, not scientific
#Date: 2021/06/05
#Author: Steven Huang, Auckland, NZ
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import pandas as pd

#matplotlib.rcParams['figure.dpi'] = 120 #high resolution 100~300

def probablityVaccine(p, N): #1-(1-p)^N
    """
    p: Vaccine effectiveness
    N: Number of courses of vaccine
    """
    return np.round(1-np.power(1-p, N), 6)

def plotVaccins(data):
    ax = plt.subplot(1,1,1)
    plt.title('Success probability after numbers of vaccination')

    markers=['o', 'v', '*', 's', '^']
    for i, d in enumerate(data):
        name,prob = d
        x = np.arange(len(prob))+1
        y = prob
        ax.plot(x,y,label=name, linestyle='-.', marker=markers[i])

    plt.text(2.5, 0.3, r'$Prob = 1-(1-p)^N$', fontsize=12)

    ax.set_xlabel('Times')
    ax.set_ylabel('Probablity')
    ax.legend()
    #plt.legend()
    plt.grid(linestyle='-.', alpha=0.5) #'-', '--', '-.', ':', '',
    #plt.legend(loc='lower left')
    plt.savefig(r'.\images\probVaccine.png')
    plt.show()
    pass

def plotVaccinsTable(data):
    columns = ['name', '1', '2', '3', '4', '5', '6']
    df  = pd. DataFrame()
    for name,prob in data:
        dfLine = pd.DataFrame([[name, prob[0], prob[1],prob[2],prob[3],prob[4],prob[5]]], columns=columns)
        df = df.append(dfLine)
    print(df)

    title = 'Success probability after numbers of vaccination'
    #plt.title(title)
    plt.text(0.16, 0.7, title, fontsize=12)
    tb = plt.table(cellText=df.values, colLabels=df.columns, loc='center',cellLoc='center')
    tb.auto_set_font_size(False)
    tb.set_fontsize(10)
    #colList = list(range(len(df.columns)))
    colList = [1,2,3,4,5,6]
    tb.auto_set_column_width(col=colList)

    plt.axis('off')
    plt.tight_layout()
    plt.savefig(r'.\images\probVaccineT.png')
    plt.show()

def generateData():
    pl = [0.2, 0.5, 0.6, 0.8, 0.9]
    N = np.arange(1, 7)

    data = []
    for p in pl:
        prob = probablityVaccine(p, N)
        #print(prob)
        data.append(('vaccine-'+str(p), prob))
    print(data)
    return data

def main():
    data = generateData()
    plotVaccins(data)
    plotVaccinsTable(data)

if __name__=="__main__":
    main()


#!/usr/bin/env python3

import numpy as np

from sigmoid import sigmoid

def lrCostFunction(theta, X, y, lambda_value):
    #LRCOSTFUNCTION Compute cost and gradient for logistic regression with
    #regularization
    #   J = LRCOSTFUNCTION(theta, X, y, lambda) computes the cost of using
    #   theta as the parameter for regularized logistic regression and the
    #   gradient of the cost w.r.t. to the parameters.

    # Initialize some useful values
    m = y.size # number of training examples
    if y.dtype == bool:
        y = y.astype(int)

    # You need to return the following variables correctly
    J = 0
    grad = np.zeros(theta.shape)

    # ====================== YOUR CODE HERE ======================
    # Instructions: Compute the cost of a particular choice of theta.
    #               You should set J to the cost.
    #               Compute the partial derivatives and set grad to the partial
    #               derivatives of the cost w.r.t. each parameter in theta
    #
    # Hint: The computation of the cost function and gradients can be
    #       efficiently vectorized. For example, consider the computation
    #
    #           sigmoid(X * theta)
    #
    #       Each row of the resulting matrix will contain the value of the
    #       prediction for that example. You can make use of this to vectorize
    #       the cost function and gradient computations.
    #
    # Hint: When computing the gradient of the regularized cost function,
    #       there're many possible vectorized solutions, but one solution
    #       looks like:
    #           grad = (unregularized gradient for logistic regression)
    #           temp = theta;
    #           temp(1) = 0;   % because we don't add anything for j = 0
    #           grad = grad + YOUR_CODE_HERE (using the temp variable)
    #

    h = sigmoid(np.dot(X, theta))
    cost = np.sum(np.dot(-y.T, np.log(h)) - np.dot((1 - y.T), np.log(1 - h)))
    J = (cost / m) + (lambda_value / (2 * m)) * np.sum(theta[1:] ** 2)
    extra = lambda_value * theta
    extra[0] = 0
    grad = (np.dot(X.T, h - y) + extra.T) / m
    return (J, grad)

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

    return (J, grad)

    #grad = grad(:);

    #end