'''
  File: compress.py

  Author: Thomas Kost

  Date: 02 August 2021

  @breif performing simple image compression using a fourier basis
 '''
import numpy as np
from utility import *
import matplotlib.pyplot as plt
import cv2 as cv
import matplotlib as mpl
def compress(image : np.array, percentage: float, debug: bool  = False)->np.array:

    max_pixel_value = 256

    # Normalize by max value of an image pixel
    image = image/max_pixel_value

    # Take FFT of each pixel type
    rFimg = np.fft.fft2(image[:,:,0])
    gFimg = np.fft.fft2(image[:,:,1])
    bFimg = np.fft.fft2(image[:,:,2])

    # Plot Spectrums when debug requested
    if debug:
        plt.figure()
        plt.subplot(1,3,1)
        plt.imshow(np.log10(abs(np.fft.fftshift(rFimg))))
        plt.axis("off")
        plt.title("Red FFT")
        plt.subplot(1,3,2)
        plt.imshow(np.log10(abs(np.fft.fftshift(gFimg))))
        plt.axis("off")
        plt.title("Green FFT")
        plt.subplot(1,3,3)
        plt.imshow(np.log10(abs(np.fft.fftshift(bFimg))))
        plt.axis("off")
        plt.title("Blue FFT")

    # Sort FFT by magnitude
    rFimg_flat = np.sort(abs(rFimg.flatten()))
    gFimg_flat = np.sort(abs(gFimg.flatten()))
    bFimg_flat = np.sort(abs(bFimg.flatten()))

    # Find magnitude threshold for retaining Data
    max_val_red = rFimg_flat[int(len(rFimg_flat)*(1.0-percentage))]
    max_val_green = rFimg_flat[int(len(gFimg_flat)*(1.0-percentage))]
    max_val_blue = rFimg_flat[int(len(rFimg_flat)*(1.0-percentage))]

    # Create and apply data mask to keep top X percent of values
    r_mask = abs(rFimg) > max_val_red
    g_mask = abs(gFimg) > max_val_green
    b_mask = abs(bFimg) > max_val_blue
    rFimg = rFimg*r_mask
    gFimg = gFimg*g_mask
    bFimg = bFimg*b_mask

    # Perform IFFT
    r_img = np.fft.ifft2(rFimg)
    g_img = np.fft.ifft2(gFimg)
    b_img = np.fft.ifft2(bFimg)

    # Recombine colors de-normalize and cast as integer
    comp_img = (np.dstack((abs(r_img),abs(g_img), abs(b_img)))*max_pixel_value).astype(np.uint8)
    return comp_img

if __name__ == "__main__":
    # Read in RGB Image
    file = "../fixtures/jelly.jpg"
    img = read(file)

    #compress image
    compressed = compress(img, 0.05, True)

    # Plot Original image
    plt.figure()
    plt.subplot(1,2,1)
    plt.title("Original Image")
    plt.imshow(img)
    plt.axis("off")

    # Plot Compressed Image
    plt.subplot(1,2,2)
    plt.imshow(compressed)
    plt.title("Compressed Image")
    plt.axis("off")

    # Display plot
    plt.show()


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Wed Sep 27 20:51:56 2017

@author: sitibanc
"""
import math
from scipy.stats import norm
import numpy as np
import matplotlib.pyplot as plt

# Black-Sholes定價模型
def blscall(s, l, t, r, sigma):
    d1 = math.log(s/l) + ( r + 0.5 * sigma ** 2) * t / sigma * math.sqrt(t)
    d2 = d1 - sigma * math.sqrt(t)
    return s * norm.cdf(d1) - l * math.exp(-r * t) * norm.cdf(d2)

# Monte-Carlo Method
def genMC():
    n = 100
    dt = t / n
    p = np.zeros([10000, n+1])

    for i in range(10000):
        p[i,0] = s
        for j in range(n):
            p[i,j+1] = p[i,j] * math.exp((r - 0.5 * sigma ** 2) * dt + np.random.normal(0, 1, 1) * sigma * math.sqrt(dt))
    return p

# 以Mote-Carlo算出的結果回推目前call option的合理價格
def getMCPrice(n, p):
    c = 0
    for i in range(n):
        if p[i,100] > l:
            c += (p[i,100] - l) / i
    return c * math.exp(-r * t)

s = 50.0
l = 40.0
t = 2.0
r = 0.08
sigma = 0.2

bls = blscall(s, l, t, r, sigma)
p = genMC()
# HW2-1-1
print("HW2-1-1: ")
plt.plot(p[:200].T)

# HW2-1-2
# Get MCPrice list
dif = [0] * 100
j = 0
# Another approach
# 直接在getMCPrice()中處理
# 處理i，當i % 100 == 99時（第n百筆），將累加的c拿出來平均i + 1，折現後存到(i + 1) / 100 - 1
for i in range(100, 10001, 100):
    dif[j] = getMCPrice(i, p) - bls
    j += 1
plt.plot(dif)


from functools import reduce
from numpy.core._rational_tests import lcm

def problem_0005(maximum: int) -> int:
    return reduce(lcm, range(1, maximum))

if __name__ == '__main__':
    MAXIMUM = 20

    print(problem_0005(MAXIMUM))
    # Expected: 232792560


# TEST: Numeric Integration using adaptive Trapezoidal and Simpson methods

import matplotlib.pyplot as plt
import numpy as np
from quad import quad_trapezoid, quad_simpson
from quad import quad_trapezoid_adapt, quad_simpson_adapt

f = lambda x: -2*x**(-3) * np.cos(x**(-2))
a = 0.5;
b = 100;
Iexp = np.sin(10**(-4)) - np.sin(4) # Expected integral value

tol = 10**(-4)  # Error tolerance

print('---------------------------------------')
# Trapezoid adaprive method with relative error
I, x = quad_trapezoid_adapt(a, b, f, tol)
E = abs(Iexp - I)/Iexp      # Relative error
n = len(x)
print('> Trapezoid adaptive method\n I = {}\n E = {}\n n = {}'.format(I, E, n))
# Trapezoid method with relative error
I = quad_trapezoid(a, b, f, n-1)
E = abs(Iexp - I)/Iexp      # Relative error
print('> Trapezoid method\n I = {}\n E = {}\n n = {}'.format(I, E, n))
# Simpson's method with relative error
I = quad_simpson(a, b, f, n-1)
E = abs(Iexp - I)/Iexp      # Relative error
print('> Simpson method\n I = {}\n E = {}\n n = {}'.format(I, E, n))

print('---------------------------------------')
# Trapezoid adaprive method with relative error
I, x = quad_simpson_adapt(a, b, f, tol)
E = abs(Iexp - I)/Iexp      # Relative error
n = len(x)
print('> Simpson adaptive method\n I = {}\n E = {}\n n = {}'.format(I, E, n))
# Trapezoid method with relative error
I = quad_trapezoid(a, b, f, n-1)
E = abs(Iexp - I)/Iexp      # Relative error
print('> Trapezoid method\n I = {}\n E = {}\n n = {}'.format(I, E, n))
# Simpson's method with relative error
I = quad_simpson(a, b, f, n-1)
E = abs(Iexp - I)/Iexp      # Relative error
print('> Simpson method\n I = {}\n E = {}\n n = {}'.format(I, E, n))

# Plot function graph using the last Simpson nodes
N = 10000    # Number of points for a smooth plot
X = np.linspace(a, b, N)
#plt.plot(X, f(X))
fig, ax = plt.subplots()
ax.semilogx(X, f(X))

y = [ f(xi) for xi in x ]
for xi in x:
    ax.semilogx([xi,xi], [0, f(xi)],
             color='black', linestyle='dashed', linewidth=1)
plt.scatter(x, y, linewidths=0.2, marker='+')
plt.grid(True)
plt.show();


import numpy as np
import numexpr as ne
import pdb

def cumavg(m):
    cumsum= np.cumsum(m)
    return cumsum / np.arange(1, cumsum.size + 1)

def RSE(pred, true):
    return np.sqrt(np.sum((true-pred)**2)) / np.sqrt(np.sum((true-true.mean())**2))

def CORR(pred, true):
    u = ((true-true.mean(0))*(pred-pred.mean(0))).sum(0)
    d = np.sqrt(((true-true.mean(0))**2*(pred-pred.mean(0))**2).sum(0))
    return (u/d).mean(-1)

def MAE(pred, true):

    return np.mean(np.abs(pred-true))
    #return ne.evaluate('sum(abs(pred-true))')/true.size
def MSE(pred, true):
    return np.mean((pred-true)**2)

def RMSE(pred, true):
    return np.sqrt(MSE(pred, true))

def MAPE(pred, true):
    return np.mean(np.abs((pred - true) / true))
    #return ne.evaluate('sum(abs(pred-true)/true)')/true.shape[0]
    #return 0
    #return ne.evaluate('sum(abs(pred-true))')/(true.size)

def MSPE(pred, true):
    return np.mean(np.square((pred - true) / true))
    #return 0

def metric(pred, true):

    mae = MAE(pred, true)
    mse = MSE(pred, true)
    rmse = RMSE(pred, true)
    mape = MAPE(pred, true)
    mspe = MSPE(pred, true)

    return mae,mse,rmse,mape,mspe


import numpy as np
import matplotlib.pyplot as plt

N = 50
x_start, x_end = -2.0, 2.0
y_start, y_end = -1.0, 1.0
x = np.linspace(x_start, x_end, N)
y = np.linspace(y_start, y_end, N)
X, Y = np.meshgrid(x, y)

kappa = 1.0
x_doublet, y_doublet = 0.0, 0.0

def get_velocity_doublet(strength, xd, yd, X, Y):
    u = (- strength / (2 * np.pi) *
         ((X - xd)**2 - (Y - yd) ** 2) / ((X - xd)**2 + (Y - yd)**2)**2)
    v = (- strength / (2 * np.pi) * 2 * (X - xd) * (Y - yd) /
         ((X - xd)**2 + (Y - yd)**2)**2)

    return u, v

def get_stream_function_doublet(strength, xd, yd, X, Y):
    psi = - strength / (2 * np.pi) * (Y - yd) / ((X - xd)**2 + (Y - yd)**2)

    return psi

u_doublet, v_doublet = get_velocity_doublet(kappa, x_doublet, y_doublet, X, Y)

psi_doublet = get_stream_function_doublet(kappa, x_doublet, y_doublet, X, Y)

size = 10
plt.figure(figsize=(size, (y_end - y_start) / (x_end - x_start) * size))
plt.xlabel('x', fontsize=16)
plt.ylabel('y', fontsize=16)
plt.xlim(x_start, x_end)
plt.ylim(y_start, y_end)
plt.streamplot(X, Y, u_doublet, v_doublet,
               density=2, linewidth=1, arrowsize=1, arrowstyle='->')
plt.scatter(x_doublet, y_doublet, color='#CD2305', s=80, marker='o')

plt.show()

# Uniform flow past a doublet

u_inf = 1.0

u_freestream = u_inf * np.ones((N, N), dtype=float)
v_freestream = np.zeros((N, N), dtype=float)

psi_freestream = u_inf * Y

# Superposition of the doublet on the freestream flow
u = u_freestream + u_doublet
v = v_freestream + v_doublet
psi = psi_freestream + psi_doublet

# Plots the streamlines
size = 10
plt.figure(figsize=(size, (y_end - y_start) / (x_end - x_start) * size))
plt.xlabel('x', fontsize=16)
plt.ylabel('y', fontsize=16)
plt.xlim(x_start, x_end)
plt.ylim(y_start, y_end)
plt.streamplot(X, Y, u, v, density=2, linewidth=1,
               arrowsize=1, arrowstyle='->')
plt.contour(X, Y, psi, levels=[
    0.], colors='#CD2305', linewidths=2, linestyles='solid')
plt.scatter(x_doublet, y_doublet, color='#CD2305', s=80, marker='o')

# Calculates the stagnation points
x_stagn1, y_stagn1 = +np.sqrt(kappa / (2 * np.pi * u_inf)), 0
x_stagn2, y_stagn2 = -np.sqrt(kappa / (2 * np.pi * u_inf)), 0

# Adds the stagnation points to the figure
plt.scatter([x_stagn1, x_stagn2], [y_stagn1, y_stagn2],
            color='g', s=80, marker='o')

plt.show()

# Computes the pressure coefficient field
cp = 1.0 - (u**2 + v**2) / u_inf**2

# Plots the pressure coefficient field
size = 10
plt.figure(
    figsize=(1.1 * size, (y_end - y_start) / (x_end - x_start) * size))
plt.xlabel('x', fontsize=16)
plt.ylabel('y', fontsize=16)
plt.xlim(x_start, x_end)
plt.ylim(y_start, y_end)
contf = plt.contourf(
    X, Y, cp, levels=np.linspace(-2.0, 1.0, 100), extend='both')
cbar = plt.colorbar(contf)
cbar.set_label('$C_p$', fontsize=16)
cbar.set_ticks([-2.0, -1.0, 0.0, 1.0])
cbar.ax.invert_yaxis()
plt.scatter(x_doublet, y_doublet, color='#CD2305', s=80, marker='o')
plt.contour(X, Y, psi, levels=[
    0.], colors='#CD2305', linewidths=2, linestyles='solid')
plt.scatter([x_stagn1, x_stagn2], [y_stagn1, y_stagn2],
            color='g', s=80, marker='o')

plt.show()

# Cp-angle
theta = np.linspace(0, 2 * np.pi, 100)
cp = 1 - 4 * (np.sin(theta))**2

plt.figure()
plt.plot(theta, cp, color='k', lw=3)

plt.show()


import math
import random
import matplotlib.pyplot as plt
import numpy as np
def sphere(x,y):
    return x**2+y**2
def rosenbrock(x,y):
    return 100*(x**2 - y**2)+(1-x)**2
def griewank(x,y):
    return (x**2+y**2)/4000  - math.cos(x)*math.cos(y/math.sqrt(2))+1
def RandomNeighbour(x,y,StepSize,Function,Limits):
    x_values = [-StepSize+x,x,x+StepSize]
    y_values = [-StepSize+y,y,y+StepSize]
    Neighbours = []
    for i in x_values:
        for j in y_values:
            if Limits[0]<= i <=Limits[1] and Limits[2] <= j <=Limits[3]:

                Neighbours.append((Function(i,j),i,j))
    return Neighbours[random.randint(0,len(Neighbours)-1)]

Solution = list()
values = set()
def SimulatedAnnealing(Function,Limits,Step,IsMax):
    Temp= 1000
    EndTemp = 0.0000000000001
    Alpha = 0.8
    x = random.uniform(Limits[0],Limits[1])
    y = random.uniform(Limits[2],Limits[3])

    while Temp > EndTemp:
        for i in range(10):
            if IsMax:

                trial = RandomNeighbour(x,y,Step,Function,Limits)
                current = Function(x,y)
                delta = trial[0] - current
                values.add((x,y))
                if delta >0 :
                    x,y = trial[1],trial[2]

                else:
                    m = math.exp(delta/Temp)
                    p = random.uniform(0,1)
                    if p < m:
                        x,y = trial[1],trial[2]

            else:
                current = Function(x,y)
                trial = RandomNeighbour(x,y,Step,Function,Limits)
                delta = trial[0] - current
                values.add((x,y))
                if delta <0 :
                    x,y = trial[1],trial[2]

                else:
                    m = math.exp(-delta/Temp)
                    p = random.uniform(0,1)
                    if p < m:
                        x,y = trial[1],trial[2]
            Solution.append(current)

        Temp = Temp * Alpha
    return (current,x,y)
Limits = [-5,5,-5,5]
val=SimulatedAnnealing(griewank,Limits,0.1,False)
print(val)

x_values = list()
y_values = list()
for x,y in values:
    x_values.append(x)
    y_values.append(y)

# ax[0].plot(Solution,c='Red')
# ax[1].plot(x_values,c='Blue')
# ax[2].plot(y_values,c='Green')

plt.subplot(311)
plt.plot(Solution,c="Red")
plt.ylabel("Objective Function")

plt.subplot(312)
plt.plot(x_values,c="Blue")
plt.ylabel("X-coordinates")

plt.subplot(313)
plt.plot(y_values,c="Green")
plt.ylabel("Y-coordinates")
plt.show()


# Copyright (c) 2010-2022, InterDigital
# All rights reserved.

# See LICENSE under the root folder.

# Convert a LiDAR point cloud to a range image based on spherical coordinate conversion

import numpy as np

def cart2spherical(input_xyz):
    """Conversion from Cartisian coordinates to spherical coordinates."""

    r = np.sqrt(input_xyz[:, 0] ** 2 + input_xyz[:, 1] ** 2 + input_xyz[:, 2] ** 2)
    alpha = np.arctan2(input_xyz[:, 1], input_xyz[:, 0]) # corresponding to width
    epsilon = np.arcsin(input_xyz[:, 2] / r) # corrsponding to height
    return np.stack((r, alpha, epsilon), axis = 1)

def spherical2cart(input_spherical):
    """Conversion from spherical coordinates to Cartesian coordinates."""

    x = input_spherical[:, 0] * np.cos(input_spherical[:, 1]) * np.cos(input_spherical[:, 2])
    y = input_spherical[:, 0] * np.sin(input_spherical[:, 1]) * np.cos(input_spherical[:, 2])
    z = input_spherical[:, 0] * np.sin(input_spherical[:, 2])
    return np.stack((x, y, z), axis=1)

def pc2img(h_fov, v_fov, width, height, inf, data):
    """Convert a point cloud to an 2D image."""

    data_spherical = cart2spherical(data)

    # Project the point cloud onto an image!
    x = (data_spherical[:, 1] - h_fov[0]) / (h_fov[1] - h_fov[0])
    y = (data_spherical[:, 2] - v_fov[0]) / (v_fov[1] - v_fov[0])
    x = np.round(x * (width - 1)).astype(np.int32)
    y = np.round(y * (height - 1)).astype(np.int32)

    # exclude the pixels that are out of the selected FOV
    mask = ~((x < 0) | (x >= width) | (y < 0) | (y >= height))
    x, y = x[mask], y[mask]
    range = data_spherical[:, 0][mask]
    data_img = np.ones((height, width), dtype = np.float32) * inf
    data_img[y, x] = range

    return data_img

def img2pc(h_fov, v_fov, width, height, inf, data):
    """Convert an 2D image back to the point cloud."""

    alpha = (np.arange(width) / (width - 1)) * (h_fov[1] - h_fov[0]) + h_fov[0]
    epsilon = (np.arange(height) / (height - 1)) * (v_fov[1] - v_fov[0]) + v_fov[0]
    alpha, epsilon = np.meshgrid(alpha, epsilon)
    data_pc = np.stack((data, alpha, epsilon), axis=2)
    data_pc = data_pc.reshape(-1, 3)
    data_pc = data_pc[data_pc[:, 0] < inf - 1, :]
    data_pc = spherical2cart(data_pc)

    return data_pc


import numpy as np

def gaussian_KL(mu0, Sig0, mu1, Sig1inv):
    t1 = np.dot(Sig1inv, Sig0).trace()
    t2 = np.dot((mu1 - mu0), np.dot(Sig1inv, mu1 - mu0))
    t3 = -np.linalg.slogdet(Sig1inv)[1] - np.linalg.slogdet(Sig0)[1]
    return 0.5 * (t1 + t2 + t3 - mu0.shape[0])

def weighted_post_KL(th0, Sig0inv, sigsq, X, Y, w, reverse=True):
    muw, Sigw = weighted_post(th0, Sig0inv, sigsq, X, Y, w)
    mup, Sigp = weighted_post(th0, Sig0inv, sigsq, X, Y, np.ones(X.shape[0]))
    if reverse:
        return gaussian_KL(muw, Sigw, mup, np.linalg.inv(Sigp))
    else:
        return gaussian_KL(mup, Sigp, muw, np.linalg.inv(Sigw))

def weighted_post(th0, Sig0inv, sigsq, X, Y, w):
    Sigp = np.linalg.inv(Sig0inv + (w[:, np.newaxis] * X).T.dot(X) / sigsq)
    mup = np.dot(Sigp, np.dot(Sig0inv, th0) + (w[:, np.newaxis] * Y[:, np.newaxis] * X).sum(axis=0) / sigsq)
    return mup, Sigp

def potentials(sigsq, X, Y, samples):
    XST = X.dot(samples.T)
    return -1. / 2. * np.log(2. * np.pi * sigsq) - 1. / (2. * sigsq) * (
                Y[:, np.newaxis] ** 2 - 2 * XST * Y[:, np.newaxis] + XST ** 2)


import numpy as np
import matplotlib.pyplot as plt
import matplotlib2tikz.save as tikz_save
import math

def derivative(y, h, n: int=1):
	if n == 1:
		return lambda x: (y(x + h) - y(x - h)) / (2 * h)
	else:
		return derivative(derivative(y, h, n - 1), h, 1)

def integral(y, h, a, b):
	ret = 0

	sgn = 1

	if a > b:
		sgn = -1
		a, b = b, a

	if abs(b - a) < h:
		h *= abs(b - a)

	for i in np.arange(a, b, h):
		ret += y(i) * h

	return ret * sgn

def fourier(y, h, n, a, b):
	L = (b - a) / 2
	a_0 = integral(y, h, a, b) / (2 * L)
	a_n = [0] * n
	b_n = [0] * n
	for i in range(1, n + 1):
		a_n[i - 1] = (1 / L) * integral(lambda x: y(x) * np.cos(i * np.pi * x / L), h, a, b)
		b_n[i - 1] = (1 / L) * integral(lambda x: y(x) * np.sin(i * np.pi * x / L), h, a, b)

	return lambda x: fouriereval(x, a_0, a_n, b_n, L)

def fouriereval(x, a_0, a_n, b_n, l):
	ret = a_0

	for i in range(1, len(a_n) + 1):
		ret += a_n[i - 1] * np.cos(i * np.pi * x / l)
		ret += b_n[i - 1] * np.sin(i * np.pi * x / l)

	return ret

# def f(x):
# 	if x > 2:
# 		return f(x - 4)
# 	if x < -2:
# 		return f(x + 4)
# 	return ((x**3) - 4 * x) / 4

# def f(x):
# 	if x < -1:
# 		return f(x + 2)
# 	if x > 1:
# 		return f(x - 2)
# 	return -1 if x < 0 else 1

def fx(x, n):
	if n == 1:
		return np.sin(x)
	return fx(np.sin(x) * np.pi / 2, n - 1)

# def f(x):
# 	return np.cos(np.tan(np.sin(x)))

def sirc(x):
	return np.sqrt(1 - x**2)

def f(x):
	if x < -2:
		return f(x + 4)
	if x > 2:
		return f(x - 4)
	if x < 0:
		return -sirc(x + 1)
	else:
		return sirc(x - 1)

h = 0.001

x = np.arange(-4, 4, 0.01)

# kr = lambda x: derivative(f, h, 2)(x) / ((1 + derivative(f, h)(x)**2)**(3 / 2))

# dkr = derivative(kr, h)

# dy = derivative(f, h)

fr = fourier(f, h, 101, -2, 2)

plt.plot(x, np.vectorize(f)(x))
# plt.plot(x, np.vectorize(kr)(x))
# plt.plot(x, np.vectorize(dkr)(x))
# plt.plot(x, np.vectorize(dy)(x))
plt.plot(x, np.vectorize(fr)(x))

plt.axis([-4, 4, -5, 5])

plt.title("$f(x)$")

plt.grid(True)

tikz_save("PyPlotTesting/Figurer/" + "f" + str(1) + ".tikz", figureheight='\\figureheight', figurewidth='\\figurewidth')


import numpy as np
from sklearn import datasets
from sklearn.decomposition import PCA

def my_pca(x,k):
	#step1 所有样本区中心化
	avg = np.average(x,axis=0)
	x = x - avg
	#step2 计算x的协方差矩阵
	mat = np.cov(x.T)
	print(mat.shape)
	#step3 计算协方差矩阵的特征值和特征向量,并选取前k个特征向量
	a,b = np.linalg.eig(mat)
	np.linalg.eig(b)
	index = np.argsort(-a) #降序排序
	p = b[index][:,:k]
	#step4 Y=PX得到降维后的数据
	return x@p

if __name__ == "__main__":

	data = datasets.load_boston()["data"]
	print(data.shape)

	pca = PCA(n_components=2)
	pca.fit(data)
	print(pca.transform(data))

	print(my_pca(data,2))


import numpy as np
import math

# 激活函数

# sigmoid函数
def sigmoid(x):
    x_ravel = x.ravel()  # 将numpy数组展平
    length = len(x_ravel)
    y = []
    for index in range(length):
        curr = x_ravel[index]
        if curr >= 0:
            a = math.exp(-curr)
            y.append(1.0 / (1 + a))
        else:
            a = math.exp(curr)
            y.append(a / (a + 1))

    return np.array(y).reshape(x.shape)

# sigmoid函数
def d_sigmoid(x):
    return pow(sigmoid(x), 2)

# relu函数
def ReLU(x):
    return 1 * (x > 0) * x

def d_ReLU(x):
    y = (x > 0) * 1
    return y

if __name__ == '__main__':
    arr = np.array([
        [19, 44]
        , [20, -21]
        , [10, -3]
    ])

    print(arr.shape)
    print(ReLU(arr))
    print(d_ReLU(arr))


import numpy.matlib as M

def haar_matrix(dim):
    '''
    Generate haar transformation matrix.
    '''
    Q = M.matrix('1 1;-1 1')
    return 1 / M.sqrt(2) * M.kron(M.eye(dim / 2), Q)

def permutation_matrix(dim):
    '''
    Generate haar permuation matrix.
    '''
    I = M.eye(dim, dim)
    return M.concatenate((I[::2][:],
                          I[1::2][:]))

def haar_forward(image, dim=None, recursive=True):
    '''
    Apply haar transformation to image.

    :param image: square matrix
    :param dim: dimension
    :param recursive: apply recursively
    :return: None
    '''
    if dim is None:
        dim = M.shape(image)[0]

    if dim == 1:  # base case
        return

    P = permutation_matrix(dim)
    T = haar_matrix(dim)

    image[0:dim, 0:dim] = P * T * M.asmatrix(image[0:dim, 0:dim]) * T.T * P.T

    if recursive:
        haar_forward(image, dim / 2)

def haar_inverse(image, dim=2):
    '''
    Apply haar inverse transformation.

    :param image: square matrix
    :param dim: dimension
    :return: None
    '''
    P = permutation_matrix(dim)
    T = haar_matrix(dim)

    image[0:dim, 0:dim] = T.T * P.T * M.asmatrix(image[0:dim, 0:dim]) * P * T

    if dim == M.shape(image)[0]:
        return

    haar_inverse(image, dim * 2)


import numpy as np

def rot_x(phi):
    """Calculates a rotation matrix around the x-axis for the angle phi.

    Parameters
    ----------
    phi : float
        The value of the angle in radians.

    Return
    ------
    3x3 matrix
        A 3x3 matrix, such that its multiplication with a vector will rotate the vector by phi radians around the x-axis.
    """
    sin_phi = np.sin(phi)
    cos_phi = np.cos(phi)
    rot_mat = np.matrix([
        [1, 0, 0],
        [0, cos_phi, sin_phi ],
        [0, -sin_phi, cos_phi]])
    return rot_mat

def rot_y(phi):
    """Calculates a rotation matrix around the y-axis for the angle phi.

    Parameters
    ----------
    phi : float
        The value of the angle in radians.

    Return
    ------
    3x3 matrix
        A 3x3 matrix, such that its multiplication with a vector will rotate the vector by phi radians around the y-axis.
    """
    sin_phi = np.sin(phi)
    cos_phi = np.cos(phi)
    rot_mat = np.matrix([
        [cos_phi, 0, sin_phi ],
        [0, 1, 0],
        [-sin_phi, 0, cos_phi]])
    return rot_mat

def rot_x_optimzed(phi):
    n = len(phi)

    sin_phi = np.sin(phi).reshape((n, 1))
    cos_phi = np.cos(phi).reshape((n, 1))

    rotx = np.zeros((n, 3, 3))
    rotx[:, 1::3, 1] = cos_phi
    rotx[:, 1::3, 2] = sin_phi
    rotx[:, 2::3, 1] = -sin_phi
    rotx[:, 2::3, 2] = cos_phi
    rotx[:, 0::3, 0] = np.ones((n, 1))

    return rotx

def rot_y_optimzed(psi):
    n = len(psi)

    sin_psi = np.sin(psi).reshape((n, 1))
    cos_psi = np.cos(psi).reshape((n, 1))

    roty = np.zeros((n, 3, 3))
    roty[:, 0::3, 0] = cos_psi
    roty[:, 0::3, 2] = sin_psi
    roty[:, 2::3, 0] = -sin_psi
    roty[:, 2::3, 2] = cos_psi
    roty[:, 1::3, 1] = np.ones((n, 1))

    return roty

if __name__ == "__main__":
    a = np.array([1,2,3,4])
    b = np.array([1,2,3,4])
    c = rot_x_optimzed(a)
    d = rot_y_optimzed(b)
    print(c)
    print(d)


import numpy as np
import pandas as pd
import pickle
from matplotlib import pyplot as plt
from sklearn.decomposition import TruncatedSVD
from sklearn.preprocessing import StandardScaler
from sklearn.cluster import KMeans
from sklearn.metrics.pairwise import euclidean_distances
from sklearn import metrics
from scipy.spatial.distance import cdist
from sklearn.metrics import silhouette_samples, silhouette_score

def elbow_method(data, save_folder):
	cluster_range = range( 1, 20 )
	cluster_errors = []
	for num_clusters in cluster_range:
		clusters = KMeans(init='k-means++', n_clusters =num_clusters, random_state=896)
		clusters.fit(data)
		#cluster_labels = clusters.fit_predict(data)
		cluster_errors.append(clusters.inertia_)
		#cluster_errors.append(sum(np.min(cdist(data, clusters.cluster_centers_, 'euclidean'), axis=1)) / data.shape[0])
		#cluster_errors.append(silhouette_score(data, cluster_labels))
	clusters_df = pd.DataFrame( { "num_clusters":cluster_range, "cluster_errors": cluster_errors })
	plt.figure(figsize=(12,8))
	plt.title('Elbow method')
	plt.xlabel('# clusters')
	plt.ylabel('inertia')
	plt.plot(clusters_df.num_clusters, clusters_df.cluster_errors, "bo-")
	plt.xticks(np.arange(1,20), np.arange(1,20))
	plt.grid()
	plt.savefig('{0}/elbow_method.png'.format(save_folder))
	plt.show()

root_folder = '/home/vijin/iith/ds-projects/data/text-analysis'
folder_dataset_1 = '{0}/{1}'.format(root_folder, 'dataset1')
folder_dataset_2 = '{0}/{1}'.format(root_folder, 'dataset2')
doc_term = 'doc_term_matrix_50000.pkl'
vocab_file = 'vocabulary_50000.pkl'
top_words = 'top_words.txt'

def cluster_analysis(root_folder, no_dims = 2, no_clusters = 6):
	print('Loading document-term matrix and vocabulary.....')
	# load the document term matrix and vocabulary
	with open('{0}/{1}'.format(root_folder, doc_term),'rb')as fp:
		doc_term_matrix = pickle.load(fp)
	with open('{0}/{1}'.format(root_folder, vocab_file),'rb')as fp:
		vocab = pickle.load(fp)
	inverted_vocab = {v: k for k, v in vocab.items()}

	print('Dimension reduction by Truncated SVD.....')
	svd = TruncatedSVD(n_components=no_dims, n_iter=7, random_state=42)
	reduced_matrix = svd.fit_transform(doc_term_matrix.T)

	scaler = StandardScaler()
	X_scaled = scaler.fit_transform(reduced_matrix)

	#print('Elbow method.....')
	#elbow_method(X_scaled, root_folder)

	print('Clustering started.....')
	kmeans = KMeans(init='k-means++', n_clusters=no_clusters, random_state=124)
	kmeans.fit(X_scaled)

	print('Finding top 5 words in clusters...')
	top_words_file = open('{0}/{1}'.format(root_folder,top_words), 'w')
	for i,center in enumerate(kmeans.cluster_centers_):
	    dist = euclidean_distances(X_scaled , center.reshape(-1, 2))
	    top_words_file.write('######### Cluster : {0} ##########\n'.format(i+1))
	    top_words_file.write('{0}\n'.format([inverted_vocab[x] for x in dist.flatten().argsort()[:5]]))
	top_words_file.close()

# number of clusters are identified by elbow method
cluster_analysis(folder_dataset_1, no_clusters=6)
cluster_analysis(folder_dataset_2, no_clusters=7)


import sys
import numpy as np

def ang2mat(angle_data):
    alpha = angle_data[0]
    beta  = angle_data[1]
    gama  = angle_data[2]

    alpha_mat = np.matrix(np.eye(3))
    beta_mat = np.matrix(np.eye(3))
    gama_mat = np.matrix(np.eye(3))
    alpha_mat[1,1] =  np.cos(alpha)
    alpha_mat[1,2] = -np.sin(alpha)
    alpha_mat[2,1] =  np.sin(alpha)
    alpha_mat[2,2] =  np.cos(alpha)

    beta_mat[0,0] =  np.cos(beta)
    beta_mat[0,2] = -np.sin(beta)
    beta_mat[2,0] =  np.sin(beta)
    beta_mat[2,2] =  np.cos(beta)

    gama_mat[0,0] =  np.cos(gama)
    gama_mat[0,1] = -np.sin(gama)
    gama_mat[1,0] =  np.sin(gama)
    gama_mat[1,1] =  np.cos(gama)

    result_mat = gama_mat*beta_mat*alpha_mat
    return result_mat
def mat2ang(mat_data):
    alpha = np.arctan2(mat_data[2,1],mat_data[2,2])
    beta  = np.arctan2(mat_data[2,0],np.sqrt(mat_data[2,2]*mat_data[2,2]+mat_data[2,1]*mat_data[2,1]))
    gama  = np.arctan2(mat_data[1,0],mat_data[0,0])
    return [alpha,beta,gama]
def angpos2mat(angpos_data):
    result_mat = np.matrix(np.eye(4))
    result_mat[0:3,0:3] = ang2mat(angpos_data[3:6])
    result_mat[0:3,3]   = np.matrix(angpos_data[0:3]).T
    return result_mat
def mat2angpos(mat_data):
    result = np.zeros((6))
    result[0:3] = np.array(mat_data[0:3,3].T)
    result[3:6] = mat2ang(mat_data[0:3,0:3])
    return result

if True:
    file_name = sys.argv[1]

    data = np.loadtxt(file_name)

    data_size = data.shape[0]
    all_angpos = np.zeros((data_size-1,6))
    pose_last =np.matrix(np.eye(4,4))
    pose =np.matrix(np.eye(4,4))
    pose_last[0:3,:] = np.matrix(data[0,:].reshape(3,4))
    for i in range(1,data_size):
        pose[0:3,:] = np.matrix(data[i,:].reshape(3,4))
        motion = pose_last.I*pose
        angpos = mat2angpos(motion)
        all_angpos[i-1,:] = angpos
        pose_last = pose.copy()
        #print pose_line
    np.savetxt(sys.argv[2],all_angpos)
    print 'done'


import numpy as np
import jax.numpy as jnp

def radial_profile(data):
  """
  Compute the radial profile of 2d image
  :param data: 2d image
  :return: radial profile
  """
  center = data.shape[0]/2
  y, x = jnp.indices((data.shape))
  r = jnp.sqrt((x - center)**2 + (y - center)**2)
  r = r.astype('int32')

  tbin = jnp.bincount(r.ravel(), data.ravel())
  nr = jnp.bincount(r.ravel())
  radialprofile = tbin / nr
  return radialprofile

def measure_power_spectrum(map_data, pixel_size):
  """
  measures power 2d data
  :param power: map (nxn)
  :param pixel_size: pixel_size (rad/pixel)
  :return: ell
  :return: power spectrum

  """
  data_ft = jnp.fft.fftshift(jnp.fft.fft2(map_data)) / map_data.shape[0]
  nyquist = np.int(map_data.shape[0]/2)
  power_spectrum_1d =  radial_profile(jnp.real(data_ft*jnp.conj(data_ft)))[:nyquist] * (pixel_size)**2
  k = np.arange(power_spectrum_1d.shape[0])
  ell = 2. * np.pi * k / pixel_size / 360
  return ell, power_spectrum_1d

def make_power_map(power_spectrum, size, kps=None, zero_freq_val=1e7):
  #Ok we need to make a map of the power spectrum in Fourier space
  k1 = np.fft.fftfreq(size)
  k2 = np.fft.fftfreq(size)
  kcoords = np.meshgrid(k1,k2)
  # Now we can compute the k vector
  k = np.sqrt(kcoords[0]**2 + kcoords[1]**2)
  if kps is None:
    kps = np.linspace(0,0.5,len(power_spectrum))
  # And we can interpolate the PS at these positions
  ps_map = np.interp(k.flatten(), kps, power_spectrum).reshape([size,size])
  ps_map = ps_map
  ps_map[0,0] = zero_freq_val
  return ps_map # Carefull, this is not fftshifted


import numpy as np
from numpy.linalg import matrix_rank
from numpy.linalg import svd
from numpy.linalg import cond
from numpy.linalg import solve
import matplotlib.pyplot as plt

def readFile(fileName):
    returnContent = []
    with open(fileName,'r') as f:
        contents = f.readlines()
        for i in contents:
            returnContent.append(i.split(","))
        for i in returnContent:
            i[len(i)-1] = i[len(i)-1].replace("\n","")

        return returnContent

def helper():
    print("\n\n\n\n")

def getTranspose(matrix):
    tMatrix = [[0 for j in range(len(matrix[0]))] for i in range(len(matrix))]
    for i in range(len(matrix)):
        for j in range(len(matrix[0])):
            tMatrix[j][i] = matrix[i][j]
    return tMatrix

def isSymmetrical(matrix):
    if len(matrix) != len(matrix[0]):
        return False
    tMatrix = getTranspose(matrix)
    for i in range(len(matrix)):
        for j in range(len(matrix[0])):
            if matrix[i][j] != tMatrix[i][j]:
                # print(i,j)
                # print(matrix[i][j])
                # print(tMatrix[i][j])
                # print(matrix[j][i])
                return False
    return True

def isDiagonal(matrix):
    for i in range(len(matrix)):
        for j in range(len(matrix[0])):
            if i != j and matrix[i][j] != 0:
                return False
    return True

def isOrthogonal(matrix):
    if len(matrix) != len(matrix[0]):
        return False
    tMatrix = getTranspose(matrix)                                                      #Transposed Matrix
    rMatrix = np.matmul(matrix,tMatrix)                                                 #Result Matrix
    for i in range(len(matrix)):
        if rMatrix[i][i] != 1:
            return False
    return isDiagonal(rMatrix)

def getSVD(matrix):
    u,s,h = svd(matrix)
    return min(s),max(s)

def generateRight(matrix):
    n = len(matrix)
    m = 1
    b = []
    for i in range(5):
        b = np.random.rand(n,m)
        try:
            x = solve(matrix,b)
            # print("{}. b = {}".format(i+1,b))
            # print("X found: {}".format(x))
        except:
            print("\nError - Couldn't find a valid x")
            return
    print("No problem finding a solution 5 randomly generated right-hand-sides (i.e. b)")

def nonZeroGraph(matrix):
    plt.spy(matrix,markersize='3')
    plt.grid('on')
    plt.title("Non-Zero Elements")
    plt.xlabel("col")
    plt.ylabel("row")
    plt.show()

def magHeatMap(matrix):
    plt.imshow(abs(matrix),cmap="hot",interpolation='nearest')
    plt.title("Magnitude of Elements")
    plt.xlabel("col")
    plt.ylabel("row")
    plt.colorbar()
    plt.show()

    pass

def mainHwFunction(fileName):
    contents = readFile(fileName)
    print("Data for: " + fileName)
    print("Matrix Dimentions : {} by {}".format(len(contents),len(contents[0])))        #Q1: Matrix Dimensions
    matrix = np.array(contents,dtype=float)
    print("Number of Non Zero Elements: {}".format(len(matrix[matrix != 0])))           #Q2: Zero Elements
    print("Is Symmetrical: {}".format(isSymmetrical(matrix)))                           #Q3: Symmetry
    print("Is Diagonal: {}".format(isDiagonal(matrix)))                                 #Q4: Diagonal
    print("Is Orthogonal: {}".format(isOrthogonal(matrix)))                             #Q5: Orthogonal
    print("Rank of Matrix: {}".format(matrix_rank(matrix)))                             #Q6: Rank
    min,max = getSVD(matrix)
    print("Smallest Singular Value: {} \nLargest Singular Value: {}".format(min,max))   #Q7&8: SVD
    print("Condition Number: {}".format(cond(matrix)))                                  #Q9: Condition Number
    generateRight(matrix)                                                               #Q10: Solving for a random b  (Ax = b)
    nonZeroGraph(matrix)
    magHeatMap(matrix)

mainHwFunction("mat5.txt")


"""
Solves the binary knapsack problem using a heuristic based on the
utility/weight ratio of the available elements.
"""

import numpy as np

def knapsack(weights, utilities, knapsack_weight):
    """
    Uses a greedy algorithm to solve the binary knapsack problem:
    1. Order the utility/weight (descendent)
    2. Put item in bag if it fits, else go to next item
    """
    weights, utilities = np.array(weights), np.array(utilities)
    number_of_items = weights.size

    benefits = utilities / weights

    ordered_indexes = np.argsort(benefits)[::-1]

    solution = np.zeros(number_of_items)

    # puts the item in the bag and if it excedes the weight, remove it from
    # bag and goes to the next iteration
    for i in ordered_indexes:
        solution[i] = 1
        if (solution * weights).sum() > knapsack_weight:
            solution[i] = 0

    return solution


import numpy as np
import scipy.linalg
from functools import partial

def fourier_diff_matrix(N, p=1):
    '''
    Returns spectral differentiation matrix of order p built on a grid x_j = jh where j = 1...N.
    The periodic interval is then (0; 2 pi].
    '''
    h = 2.*np.pi / N
    if p == 1:
        return scipy.linalg.circulant([1./2 * (-1)**j / np.tan(j*h/2.) if j != 0 else 0 for j in range(N)])
    elif p == 2:
        return scipy.linalg.circulant([-1./2 * (-1)**j / np.sin(j*h/2.)**2 if j != 0 else -np.pi**2 / (3.*h**2) - 1./6 for j in range(N)])
    Exception('p = {} is not implemented!'.format(p))

def cheb_points(N):
    '''
    Returns N Chebyshev points: x_j = cos(j pi / N) where j = 0,...,N.
    '''
    jj = np.arange(0, N + 1)
    return np.cos(jj*np.pi / N)

def cheb_diff_matrix(N, p=1):
    '''
    Returns spectral differentiation matrix of order p built on a grid x_j = cos(j pi / N) where j = 0,...,N.
    The interval is then [-1; 1].
    '''
    c = lambda idx: 2 if idx == 0 or idx == N else 1
    xx = cheb_points(N)
    D = np.zeros((N + 1, N + 1))
    for i in range(D.shape[0]):
        for j in range(D.shape[0]):
            if i != j:
                D[i, j] = c(i) / c(j) * (-1)**(i+j) / (xx[i] - xx[j])
        D[i, i] = -np.sum(D[i, :])
    return np.linalg.matrix_power(D, p)

def spectral_diff_via_matrix_multiplication(v, D_matrix=None, D_matrix_builder=fourier_diff_matrix):
    if D_matrix is None:
        D_matrix = D_matrix_builder()
    return np.dot(D_matrix, v)

def fourier_diff_via_matrix_multiplication(v, D_matrix=None):
    return spectral_diff_via_matrix_multiplication(v, D_matrix=D_matrix, D_matrix_builder=partial(fourier_diff_matrix, len(v)))

def cheb_diff_via_matrix_multiplication(v, D_matrix=None):
    return spectral_diff_via_matrix_multiplication(v, D_matrix=D_matrix, D_matrix_builder=partial(cheb_diff_matrix, len(v) - 1))

def fourier_diff_via_fft(v, order):
    N = len(v)
    if N % 2 != 0:
        Exception('Only even number of nodes can be considered')
    hat_v = np.fft.fft(v)
    diff_coeffs = np.array([(1j * k)**order for k in list(range(int(N//2))) + list(range(int(-N//2), 0))]) # it replicates the standard order of the Fourier coefficients in hat_v:
    # A[0] contains the zero-frequency term, A[1:n/2] contains the positive-frequency terms,
    # and A[n/2+1:] contains the negative-frequency terms, in order of decreasingly negative frequency.
    hat_w = diff_coeffs * hat_v
    return np.fft.ifft(hat_w)

def cheb_diff_via_fft(v, order):
    N = len(v) - 1
    x = cheb_points(N)
    V_ = np.r_[v, v[-2:0:-1]] # V = [v_0, ..., v_N, v_{N-1}, ..., v_1]
    hat_V = np.fft.fft(V_)
    diff_coeffs = np.array([(1j * k)**order for k in list(range(N)) + list(range(-N, 0))]) # it replicates the standard order of the Fourier coefficients in hat_v:
    # A[0] contains the zero-frequency term, A[1:n/2] contains the positive-frequency terms,
    # and A[n/2+1:] contains the negative-frequency terms, in order of decreasingly negative frequency.
    hat_W = diff_coeffs * hat_V
    W_ = np.real(np.fft.ifft(hat_W))
    w = np.zeros_like(v)
    w[1:-1] = np.array([-W_[i] / np.sqrt(1 - x[i]**2) for i in range(1, N)])
    w[0] = 1./N * (np.sum([i**2 * np.real(hat_V[i]) for i in np.arange(1, N)]) + 1./2 * N**2 * np.real(hat_V[N]))
    w[N] = 1./N * (np.sum([(-1)**(i+1) * i**2 * np.real(hat_V[i]) for i in np.arange(1, N)]) + 1./2 * (-1)**(N+1) * N**2 * np.real(hat_V[N]))
#    if N % 2 != 0:
#        Exception('Only even number of nodes can be considered')
    return w


"""
Filename: quadsums.py

Authors: Thomas Sargent,  John Stachurski

This module provides functions to compute quadratic sums of the form described
in the docstrings.

"""

import numpy as np
from numpy import sqrt, dot
import scipy.linalg

def var_quadratic_sum(A, C, H, beta, x0):
    r"""
    Computes the expected discounted quadratic sum

    .. math::

        q(x_0) = E \sum_{t=0}^{\infty} \beta^t x_t' H x_t

    Here {x_t} is the VAR process x_{t+1} = A x_t + C w_t with {w_t}
    standard normal and x_0 the initial condition.

    Parameters
    ----------
    A : array_like(float, ndim=2)
        The matrix described above in description.  Should be n x n
    C : array_like(float, ndim=2)
        The matrix described above in description.  Should be n x n
    H : array_like(float, ndim=2)
        The matrix described above in description.  Should be n x n
    beta: scalar(float)
        Should take a value in (0, 1)
    x_0: array_like(float, ndim=1)
        The initial condtion. A conformable array (of length n, or with
        n rows)

    Returns
    -------
    q0: scalar(float)
        Represents the value q(x_0)

    Remarks: The formula for computing q(x_0) is q(x_0) = x_0' Q x_0 + v
    where

        Q is the solution to Q = H + beta A' Q A and
        v = \trace(C' Q C) \beta / (1 - \beta)

    """
    # == Make sure that A, C, H and x0 are array_like == #
    A, C, H = list(map(np.atleast_2d, (A, C, H)))
    x0 = np.atleast_1d(x0)
    # == Start computations == #
    Q = scipy.linalg.solve_discrete_lyapunov(sqrt(beta) * A.T, H)
    cq = dot(dot(C.T, Q), C)
    v = np.trace(cq) * beta / (1 - beta)
    q0 = dot(dot(x0.T, Q), x0) + v

    return q0

def m_quadratic_sum(A, B, max_it=50):
    r"""
    Computes the quadratic sum

    .. math::

        V = \sum_{j=0}^{\infty} A^j B A^{j'}

    V is computed by using a doubling algorithm. In particular, we
    iterate to convergence on V_j with the following recursions for j =
    1, 2,... starting from V_0 = B, a_0 = A:

    .. math::

        a_j = a_{j-1} a_{j-1}

        V_j = V_{j-1} + a_{j-1} V_{j-1} a_{j-1}'

    Parameters
    ----------
    A : array_like(float, ndim=1)
        An n x n matrix as described above.  We assume in order for
        convergence that the eigenvalues of A have moduli bounded by
        unity
    B : array_like(float, ndim=1)
        An n x n matrix as described above.  We assume in order for
        convergence that the eigenvalues of A have moduli bounded by
        unity
    max_it : scalar(int), optional(default=50)
        The maximum number of iterations

    Returns
    ========
    gamma1: array_like(float, ndim=2)
        Represents the value V

    """
    alpha0 = A
    gamma0 = B

    diff = 5
    n_its = 1

    while diff > 1e-15:

        alpha1 = alpha0.dot(alpha0)
        gamma1 = gamma0 + np.dot(alpha0.dot(gamma0), alpha0.T)

        diff = np.max(np.abs(gamma1 - gamma0))
        alpha0 = alpha1
        gamma0 = gamma1

        n_its += 1

        if n_its > max_it:
            raise ValueError('Exceeded maximum iterations of %i.' % (max_it) +
                             ' Check your input matrices')

    return gamma1


import numpy as np

def det(x):
    """
    Calculate the determinant of ndarray `x`. This is similar to np.linalg.det,
    but the square dimensions are at the beginning instead of at the end.

    Parameters
    ----------
    * `x` : array_like, shape (ndim, ndim, ...)
        An ndarray which determinant to be calculated

    Returns
    -------
    * array_like or float
        The determinant of the `x`, arranged with shape: x.shape[2:]
    """
    # shape checks
    x = np.asarray(x)
    if (len(x.shape) < 2):
        raise ValueError("x must have at least 2 dimensions")
    if x.shape[0] != x.shape[1]:
        raise ValueError("The first two dimensions must equal")

    nd = x.shape[0]
    ndim = len(x.shape)
    if nd == 1:
        return _det_1d(x, ndim)
    elif nd == 2:
        return _det_2d(x, ndim)
    elif nd == 3:
        return _det_3d(x, ndim)
    else:
        return _det_nd(x, nd, ndim)

def _det_1d(x, ndim):
    idx = tuple([0,0] + ([slice(None, None, None)] * (ndim-2)))
    return x[idx]

def _det_2d(x, ndim):
    rest_idx = [slice(None, None, None)] * (ndim-2)
    i00 = tuple([0,0] + rest_idx)
    i01 = tuple([0,1] + rest_idx)
    i10 = tuple([1,0] + rest_idx)
    i11 = tuple([1,1] + rest_idx)
    return x[i00] * x[i11] - x[i01] * x[i10]

def _det_3d(x, ndim):
    rest_idx = [slice(None, None, None)] * (ndim-2)
    i00 = tuple([0,0] + rest_idx)
    i01 = tuple([0,1] + rest_idx)
    i02 = tuple([0,2] + rest_idx)
    i10 = tuple([1,0] + rest_idx)
    i11 = tuple([1,1] + rest_idx)
    i12 = tuple([1,2] + rest_idx)
    i20 = tuple([2,0] + rest_idx)
    i21 = tuple([2,1] + rest_idx)
    i22 = tuple([2,2] + rest_idx)
    return \
        x[i00]*x[i11]*x[i22] + x[i01]*x[i12]*x[i20] + x[i02]*x[i10]*x[i21] -\
        (x[i02]*x[i11]*x[i20] + x[i00]*x[i12]*x[i21] + x[i22]*x[i01]*x[i10])

def _det_nd(x, nd, ndim):
    # rearrange matrix to have shape: outshape + [ndim, ndim]
    perm_idx = list(range(2,ndim)) + list(range(2))
    y = np.transpose(x, perm_idx)
    # calculate and return the determinant
    return np.linalg.det(y)


# Kaggle metrcis
# Krzysztof Joachimiak 2017

import numpy as np
from kaggle_metrics.utils import check_shapes, align_shape

# REGRESSION METRICS

def mean_absolute_error(y_true, y_pred):

    '''

    Mean absolute error.

    Parameters
    ----------
    y_true: ndarray
        Ground truth
    y_pred: ndarray
        Array of predictions

    Returns
    -------
    rmsle: float
        Mean absolute error

    References
    ----------
    .. [1] https://www.kaggle.com/wiki/MeanAbsoluteError

    '''

    # Check shapes
    y_true, y_pred = align_shape(y_true, y_pred)
    check_shapes(y_true, y_pred)

    return np.abs(y_true - y_pred).mean()

def weighted_mean_absolute_error(y_true, y_pred, weights):

    '''

    Weighted mean absolute error.

    Parameters
    ----------
    y_true: ndarray
        Ground truth
    y_pred: ndarray
        Array of predictions

    Returns
    -------
    rmsle: float
        Weighted mean absolute error

    References
    ----------
    .. [1] https://www.kaggle.com/wiki/WeightedMeanAbsoluteError

    '''

    # Check shapes
    y_true, y_pred = align_shape(y_true, y_pred)
    check_shapes(y_true, y_pred)

    return (weights * np.abs(y_true - y_pred)).mean()

def root_mean_squared_error(y_true, y_pred):
    '''

    Root mean squared error.

    Parameters
    ----------
    y_true: ndarray
        Ground truth
    y_pred: ndarray
        Array of predictions

    Returns
    -------
    rmsle: float
        Root mean squared error

    References
    ----------
    .. [1] https://www.kaggle.com/wiki/RootMeanSquaredError

    '''

    # Check shapes
    y_true, y_pred = align_shape(y_true, y_pred)
    check_shapes(y_true, y_pred)

    return np.sqrt(((y_true - y_pred)**2).mean())

def root_mean_squared_logarithmic_error(y_true, y_pred):
    '''

    Root mean squared logarithmic error.

    Parameters
    ----------
    y_true: ndarray
        Ground truth
    y_pred: ndarray
        Array of predictions

    Returns
    -------
    rmsle: float
        Root mean squared logarithmic error

    References
    ----------
    .. [1] https://www.kaggle.com/wiki/RootMeanSquaredLogarithmicError
    .. [2] https://www.slideshare.net/KhorSoonHin/rmsle-cost-function

    '''

    # Check shapes
    y_true, y_pred = align_shape(y_true, y_pred)
    check_shapes(y_true, y_pred)

    return np.sqrt(((np.log(y_pred + 1) - np.log(y_true + 1))**2).mean())

def mean_absolute_percentage_error(y_true, y_pred):
    '''

    Mean absolute percentage error

    Parameters
    ----------
    y_true: ndarray
    Ground truth
    y_pred: ndarray
    Array of predictions

    Returns
    -------
    mean_absolute_percentage_error: float
        Mean absolute percentage error

    References
    ----------
    .. [1] https://en.wikipedia.org/wiki/Mean_absolute_percentage_error

    '''
    return (np.abs(y_true - y_pred) / y_true).mean()

def mean_percentage_error(y_true, y_pred):
    '''

    Mean percentage error

    Parameters
    ----------
    y_true: ndarray
        Ground truth
    y_pred: ndarray
        Array of predictions

    Returns
    -------
    mean_percentage_error: float
        Mean percentage error

    References
    ----------
    .. [1] https://en.wikipedia.org/wiki/Mean_percentage_error

    '''
    return ((y_true - y_pred) / y_true).mean()

# aliases
mae = mean_absolute_error
wmae = weighted_mean_absolute_error
rmse = root_mean_squared_error
rmsle = root_mean_squared_logarithmic_error
mape = mean_absolute_error
mpe = mean_percentage_error
mean_absolute_percentage_deviation = mean_absolute_percentage_error
mapd = mean_absolute_percentage_deviation


from __future__ import division
import warnings

from scipy.misc import derivative
from scipy.optimize import fminbound as fmin

import matplotlib.pyplot as plt
from prettytable import PrettyTable as PT
from time import localtime, strftime

import numpy as np
import decimal as dm

warnings.filterwarnings("ignore")

'''-----------------------------------------------------------------------------
Functions: f(x),f'(x) and f^4(x) and error function 10^-x
-----------------------------------------------------------------------------'''
f = lambda x : (x+np.log( np.sin((x**2)+np.arctan(np.sqrt(1+(x**3))))+1))*x
f_1 = lambda x: derivative(f,x,n=1)
f_4 = lambda x: derivative(f,x,n=4,order=5)

error = lambda x: 10**(-x)

'''-----------------------------------------------------------------------------
M calculation, max|f'(x)| or max|f^4(x)| for xE]a,b[
-----------------------------------------------------------------------------'''
def M(lower,upper,simpson=True):
    if simpson:
        return abs(f(fmin(lambda x: -f_4(x),lower,upper)))
    else:
        return abs(f(fmin(lambda x: -f_1(x),lower,upper)))

'''-----------------------------------------------------------------------------
Simpson Rule for Integration Approximation
-----------------------------------------------------------------------------'''
#Organize data and display
def simpson(a,b,errors):
    table = PT()
    table.title = "Numerical Approximation for Integration using Simpson Rule"
    table.field_names = ["Error","N","Approximation M="+str(M(a,b))]

    for e in errors:
        s,n = simpsonRule(a,b,e+1)
        table.add_row([str(error(e+1)),str(n),str(dm.Decimal(s))])
    print(table)
    print("\n"*3)

#Determine n for error e
def determineNSimpson(a,b,e):
    m = M(a,b)
    v = (np.power((b-a),5)*m)/(e*180)
    v = np.power(v,(1./4.))
    m = int(v)+2 if int(v)%2==0 else int(v)+1
    return m

#Actual method
def simpsonRule(a,b,e):
    n = determineNSimpson(a,b,error(e))
    val = lambda x: 2 if (i%2==0) else 4
    h = (b-a)/n
    s = f(a)+f(b)
    for i in range(n):
        s += val(i)*f(a+i*h)
    return (h/3)*s,n

'''-----------------------------------------------------------------------------
Rectangle Rule for Integration Approximation
-----------------------------------------------------------------------------'''
#Organize data and display
def rectangle(a,b,k,d=True):
    #if d is true,it will show the graph of approximation for every k
    m = M(a,b,simpson=False) #m calculation~

    table = PT()
    table.title = "Numerical Approximation for Integration using Rectangles"
    table.field_names = ["N","Approximation M="+str(m),"Error"]

    for i in range(1,k+1):
        s,e = rectangleRule(a,b,2**i,m,d);
        er = '%.2E' %dm.Decimal(str(e))
        table.add_row([str(2**i),str(dm.Decimal(s)),er])
    print(table)
    print("\n"*3)

#Rectangle rule method
def rectangleRule(a,b,n,m,d=True):
    step = (b-a)/n
    s = 0.0
    for i in range(n):
        s += f((a+step/2)+i*step)
    s *= step
    #error calculation
    e = (np.power((b-a),2)/(n*2))*m

    if d and n<=256:#draw option
        draw(a,b,n);
    return s,e
#Draw f and approximation rectangles
def draw(a,b,n):
    v = np.linspace(a,b,n)
    plt.plot(v,f(v),color='red')
    plt.xlabel('x')
    plt.ylabel('y')
    plt.title('Numerical approximation: Rectangular, N='+str(n))
    for i in range(1,len(v)):
        c = v[i-1]
        d = v[i]
        plt.plot([c,c],[0,f((c+d)/2)],color='blue')
        plt.plot([d,d],[0,f(d)],color='blue')
        plt.plot([c,d],[f((c+d)/2),f((c+d)/2)],color='blue')
    plt.savefig("./Images/RectangleDraw_N"+str(n)+"_"+strftime("%Y%m%d_%H%M%S", localtime())+".png",dpi=300, bbox_inches="tight")
    plt.cla()
    plt.clf()
    plt.close()

#-------------------------------------------------------------------------------
disp = input("Display Rectangles Graph? (yes/no)")
disp = disp == 'yes'
print
simpson(0,1,[7,12])#apply simpson to error 7 and 12 in [0,1]
rectangle(0,1,20,d=disp) #apply rectangle in [0,1] in n points n=1(1)20


import sympy as sp, math as m

x = sp.symbols('x')
sp.init_printing(use_unicode=True)

#f=sp.Lambda(x, x*sp.cos(x)-x**2*sp.sin(x))

def f(x):
    #return x*m.cos(x)-x**2*m.sin(x)
    #return m.cos(x)
    return x**3*m.cos(x**2+3)

def lagrange(nodes):

    l = []
    for i in range(len(nodes)):
        l.append(1)
        for j in range(len(nodes)):
            if j != i:
                l[i]*=sp.poly((x-nodes[j])/(nodes[i]-nodes[j]))

    return l

def n_c(f, a, b, n):

    nodes = []
    h = (b-a)/(n+2)

    for i in range(n+1):
        k = a+(i+1)*h
        nodes.append(k)

    if n == 0:
        return (b-a)*f(a+h)

    l = lagrange(nodes)

    result = 0

    for i in range(n+1):
        result += (l[i].integrate()(b)-l[i].integrate()(a))*f(nodes[i])

    return result

n = 0
a, b = 1, 1.5

result = n_c(f, a, b, n)

print(result)

# Ej 14, punto medio:
"""
def fa(x):
    return x**2*m.log(x)

def fb(x):
    return x**3*m.exp(-x)

def fc(x):
    return 3*x/(x**2-4)

def fd(x):
    return m.cos(x)*m.exp(3*x)

print("a) " + str(n_c(fa, 1, 1.5, 0)))
print("b) " + str(n_c(fb, 0, 1, 0)))
print("c) " + str(n_c(fc, 1, 1.8, 0)))
print("d) " + str(n_c(fd, 0, m.pi/4, 0)))
"""


#T# when two numbers have no common divisor, their common divisor is then 1

#T# to calculate the greatest common divisor, the numpy package is used
import numpy as np

#T# the gcd function from the numpy package calculates the greatest common divisor of two numbers
num1 = 8
num2 = 12
num3 = np.gcd(num1, num2) # 4

#T# the reduce function from the gcd module of the numpy package calculates the greatest common divisor of a set of numbers inside a one dimensional array
arr1 = np.array([12, 18, 36, 60])
num1 = np.gcd.reduce(arr1) # 6


#A Simple Numpy Example
import numpy as np
cvalues = [25.3, 24.8, 26.9, 23.9]
#We will turn this into a one-dimensional numpy array:

C = np.array(cvalues)
print(C)
#Let's assume, we want to turn the values into degrees Fahrenheit. This is very easy to accomplish with a numpy array. The solution to our #problem can be achieved by simple scalar multiplication:

print(C * 9 / 5 + 32)
"""Compared to this, the solution for our Python list is extremely awkward:

fvalues = [ x*9/5 + 32 for x in cvalues]
print(fvalues)
"""


#%% [markdown]
# ## Simulated Signal Data Generation
# The simulated signal for this example will be constructed by the combination of two Gaussian peaks with some
# overlap.  The height of each peak will be dependent on a concentration value.  The target value for each generated
# signal will be the concentration value.  The goal of the project will be correctly classify each sample based on
# the concentration value.

#%%
import matplotlib.pyplot as plt
import matplotlib as mpl
import numpy as np
from scipy.stats import norm

mpl.style.use('seaborn-notebook')
plt.rcParams["figure.figsize"] = (12, 5)

#%% [markdown]
# The following plot shows the separate Gaussian peaks used to generate the project test signal.  This sample signal
# was derived from an example in the
# [**Rampy**](https://github.com/charlesll/rampy/blob/master/examples/Baseline_and_Centroid_determination.ipynb) project.

#%%
xnum = 600
np.random.seed(42)
x = np.arange(0, xnum, 1.0)
S_1 = norm.pdf(x, loc=310.0, scale=40.0)
S_2 = norm.pdf(x, loc=390.0, scale=20.0)
S_true = np.vstack((S_1, S_2))

fig, axs = plt.subplots()
axs.plot(x, S_1)
axs.plot(x, S_2)
fig.suptitle('Signal Base Gaussian Shapes')

#%% [markdown]
# The following plots will show the combined Gaussian peaks at varying concentration levels.  The first
# plot is generated using a fixed set of concentrations values.  The second plot generates a random set of
# curves with the line color determined from the concentration level.

#%%
C_true = np.array([[0.0, 1.0], [0.25, 0.75], [0.5, 0.5], [0.75, 0.25], [1.0, 0.0]])
signal = np.dot(C_true, S_true)

fig, axs = plt.subplots()
for i, level in enumerate(C_true):
    axs.plot(x, signal[i], label='{0:.2f}-concentration'.format(C_true[i, 0]))
fig.suptitle('Combined Signal at Varying Concentration Levels')
plt.legend()

#%%
nsamples = 100
C_levels = np.random.rand(nsamples)
C_matrix = np.vstack((C_levels, (1-C_levels))).T
samples = np.dot(C_matrix, S_true)

# norm is a class which, when called, can normalize data into the
# [0.0, 1.0] interval.
norm = mpl.colors.Normalize(vmin=np.min(C_levels), vmax=np.max(C_levels))

# create a ScalarMappable and initialize a data structure
jet = plt.get_cmap('jet')
s_m = mpl.cm.ScalarMappable(norm=norm, cmap=jet)
s_m.set_array([])

# plotting spectra
# calling the ScalarMappable that was initialised with c_m and norm
fig, axs = plt.subplots()
for i in range(nsamples):
    color = s_m.to_rgba(C_levels[i])
    axs.plot(x, samples[i, :].T, color=color)

# we plot the colorbar, using again our
# ScalarMappable
c_bar = plt.colorbar(s_m)
c_bar.set_label(r"C_")

fig.suptitle('Combined Signals Colored By Concentration Levels')
plt.xlabel('X')
plt.ylabel('Y')
plt.show()


"""This file contains code used in "Think DSP",
by Allen B. Downey, available from greenteapress.com

Copyright 2015 Allen B. Downey
License: GNU GPLv3 http://www.gnu.org/licenses/gpl.html
"""

from __future__ import print_function, division

import math
import numpy as np

import thinkdsp
import thinkplot

import matplotlib.pyplot as pyplot

import warnings
warnings.filterwarnings('ignore')

PI2 = math.pi * 2

def linear_chirp_evaluate(ts, low=440, high=880, amp=1.0):
    """Computes the waveform of a linear chirp and prints intermediate values.

    low: starting frequency
    high: ending frequency
    amp: amplitude
    """
    print('ts', ts)

    freqs = np.linspace(low, high, len(ts)-1)
    print('freqs', freqs)

    dts = np.diff(ts)
    print('dts', dts)

    dphis = np.insert(PI2 * freqs * dts, 0, 0)
    print('dphis', dphis)

    phases = np.cumsum(dphis)
    print('phases', phases)

    ys = amp * np.cos(phases)
    print('ys', ys)

    return ys

def discontinuity(num_periods=30, hamming=False):
    """Plots the spectrum of a sinusoid with/without windowing.

    num_periods: how many periods to compute
    hamming: boolean whether to apply Hamming window
    """
    signal = thinkdsp.SinSignal(freq=440)
    duration = signal.period * num_periods
    wave = signal.make_wave(duration)

    if hamming:
        wave.hamming()

    print(len(wave.ys), wave.ys[0], wave.ys[-1])
    spectrum = wave.make_spectrum()
    spectrum.plot(high=880)

def three_spectrums():
    """Makes a plot showing three spectrums for a sinusoid.
    """
    thinkplot.preplot(rows=1, cols=3)

    pyplot.subplots_adjust(wspace=0.3, hspace=0.4,
                           right=0.95, left=0.1,
                           top=0.95, bottom=0.1)

    xticks = range(0, 900, 200)

    thinkplot.subplot(1)
    thinkplot.config(xticks=xticks)
    discontinuity(num_periods=30, hamming=False)

    thinkplot.subplot(2)
    thinkplot.config(xticks=xticks, xlabel='Frequency (Hz)')
    discontinuity(num_periods=30.25, hamming=False)

    thinkplot.subplot(3)
    thinkplot.config(xticks=xticks)
    discontinuity(num_periods=30.25, hamming=True)

    thinkplot.save(root='windowing1')

def window_plot():
    """Makes a plot showing a sinusoid, hamming window, and their product.
    """
    signal = thinkdsp.SinSignal(freq=440)
    duration = signal.period * 10.25
    wave1 = signal.make_wave(duration)
    wave2 = signal.make_wave(duration)

    ys = np.hamming(len(wave1.ys))
    ts = wave1.ts
    window = thinkdsp.Wave(ys, ts, wave1.framerate)

    wave2.hamming()

    thinkplot.preplot(rows=3, cols=1)

    pyplot.subplots_adjust(wspace=0.3, hspace=0.3,
                           right=0.95, left=0.1,
                           top=0.95, bottom=0.05)

    thinkplot.subplot(1)
    wave1.plot()
    thinkplot.config(axis=[0, duration, -1.07, 1.07])

    thinkplot.subplot(2)
    window.plot()
    thinkplot.config(axis=[0, duration, -1.07, 1.07])

    thinkplot.subplot(3)
    wave2.plot()
    thinkplot.config(axis=[0, duration, -1.07, 1.07],
                     xlabel='Time (s)')

    thinkplot.save(root='windowing2')

def chirp_spectrum():
    """Plots the spectrum of a one-second one-octave linear chirp.
    """
    signal = thinkdsp.Chirp(start=220, end=440)
    wave = signal.make_wave(duration=1)

    thinkplot.preplot(3, cols=3)
    duration = 0.01
    wave.segment(0, duration).plot(xfactor=1000)
    thinkplot.config(ylim=[-1.05, 1.05])

    thinkplot.subplot(2)
    wave.segment(0.5, duration).plot(xfactor=1000)
    thinkplot.config(yticklabels='invisible',
                     xlabel='Time (ms)')

    thinkplot.subplot(3)
    wave.segment(0.9, duration).plot(xfactor=1000)
    thinkplot.config(yticklabels='invisible')

    thinkplot.save('chirp3')

    spectrum = wave.make_spectrum()
    spectrum.plot(high=700)
    thinkplot.save('chirp1',
                   xlabel='Frequency (Hz)',
                   ylabel='Amplitude')

def chirp_spectrogram():
    """Makes a spectrogram of a one-second one-octave linear chirp.
    """
    signal = thinkdsp.Chirp(start=220, end=440)
    wave = signal.make_wave(duration=1, framerate=11025)
    spectrogram = wave.make_spectrogram(seg_length=512)

    print('time res', spectrogram.time_res)
    print('freq res', spectrogram.freq_res)
    print('product', spectrogram.time_res * spectrogram.freq_res)

    spectrogram.plot(high=700)

    thinkplot.save('chirp2',
                   xlabel='Time (s)',
                   ylabel='Frequency (Hz)')

def overlapping_windows():
    """Makes a figure showing overlapping hamming windows.
    """
    n = 256
    window = np.hamming(n)

    thinkplot.preplot(num=5)
    start = 0
    for i in range(5):
        xs = np.arange(start, start+n)
        thinkplot.plot(xs, window)

        start += n/2

    thinkplot.save(root='windowing3',
                   xlabel='Index',
                   axis=[0, 800, 0, 1.05])

def invert_spectrogram():
    """Tests Spectrogram.make_wave.
    """
    signal = thinkdsp.Chirp(start=220, end=440)
    wave = signal.make_wave(duration=1, framerate=11025)
    spectrogram = wave.make_spectrogram(seg_length=512)

    wave2 = spectrogram.make_wave()

    for i, (y1, y2) in enumerate(zip(wave.ys, wave2.ys)):
        if abs(y1 - y2) > 1e-14:
            print(i, y1, y2)

def main():
    chirp_spectrum()
    chirp_spectrogram()
    overlapping_windows()
    window_plot()
    three_spectrums()

if __name__ == '__main__':
    main()


"""
Example 3 - Logistic Regression without regularization

NOTE: The example and sample data is being taken from the "Machine Learning course by Andrew Ng" in Coursera.

Problem:
  Suppose that you are the administrator of a university department and
  you want to determine each applicant’s chance of admission based on their
  results on two exams. You have historical data from previous applicants
  that you can use as a training set for logistic regression. For each training
  example, you have the applicant’s scores on two exams and the admissions
  decision.
  Your task is to build a classification model that estimates an applicant’s
  probability of admission based the scores from those two exams.

  The file 'data/ex1data1.txt' contains the dataset for our
  Logistic regression problem.
"""

# initial imports

import numpy as np
from matplotlib import pyplot as plt

plt.ion()
from models.data_preprocessing import add_bias_unit, map_feature, feature_normalize
from models.logistic_regression import cost_function, predict, gradient_descent, gradient_function, sigmoid
from models.plotter import plot_decision_boundary

data = np.loadtxt('data/ex2data2.txt', delimiter=',')
X = data[:, :-1]
y = data[:, -1, np.newaxis]

"""
==================== Part 1: Plotting ====================
  We start the exercise by first plotting the data to understand the
  the problem we are working with.
"""
print('Plotting data with + indicating (y = 1) examples and o indicating (y = 0) examples.')
"""
Example plotting for multiple markers
x = np.array([1,2,3,4,5,6])
y = np.array([1,3,4,5,6,7])
m = np.array(['o','+','+','o','x','+'])

unique_markers = set(m)  # or yo can use: np.unique(m)

for um in unique_markers:
    mask = m == um
    # mask is now an array of booleans that van be used for indexing
    plt.scatter(x[mask], y[mask], marker=um)
"""
fig, ax = plt.subplots()
y_slim = y.ravel()
# plotting y=1 values
ax.scatter(x=X[y_slim == 1, 0], y=X[y_slim == 1, 1], marker='+', color='black', s=50)
# plotting y=0 values
# X[y_slim == 0, 0] is logical indexing with rows with y=0 only
ax.scatter(x=X[y_slim == 0, 0], y=X[y_slim == 0, 1], marker='o', color='y', s=30)

# labels
ax.set_xlabel('Microchip Test 1')
ax.set_ylabel('Microchip Test 2')

# Specified in plot order
ax.legend(['y = 1', 'y = 0'])

# Adding Polynomial Features

# Note that mapFeature also adds a column of ones for us, so the intercept term is handled
X = map_feature(X, degree=6)

# ============ Part 2: Compute Cost and Gradient ============
# initial sizes
m, n = X.shape

# Initialize fitting parameters
initial_theta = np.zeros([n, 1])

# Compute and display initial cost and gradient
cost = cost_function(initial_theta, X, y, regularized=False)
grad = gradient_function(initial_theta, X, y, regularized=False)
print('Cost at initial theta (zeros): {}'.format(cost))
print('Expected cost (approx): 0.693')
print('Gradient at initial theta (zeros) - first five values only:')
print(grad[:5])
print('Expected gradients (approx) - first five values only:')
print('0.0085\n 0.0188\n 0.0001\n 0.0503\n 0.0115\n')

test_theta = np.ones([X.shape[1], 1])
cost = cost_function(test_theta, X, y, lamda=10, regularized=True)
grad = gradient_function(test_theta, X, y, lamda=10, regularized=True)

print('Cost at test theta (with lambda = 10): '.format(cost))
print('Expected cost (approx): 3.16')
print('Gradient at test theta - first five values only: {}'.format(grad[:5]))
print('Expected gradients (approx) - first five values only:')
print(' 0.3460\n 0.1614\n 0.1948\n 0.2269\n 0.0922\n')

# =========== Performing gradient descent================
from models.data_preprocessing import feature_normalize

X_norm, mu, sigma = feature_normalize(X[:, 1:])
X_norm = add_bias_unit(X_norm)

from scipy.optimize import minimize

theta_history = []  # for plotting cost vs iteration graph

def theta_store(value, *args):
    theta_history.append(value)

initial_theta = np.zeros(n)
op_result = minimize(fun=cost_function, x0=initial_theta, jac=gradient_function, args=(X, y, 1, True), method='tnc', callback=theta_store)

print('Cost at theta found by Gradient descent: {}'.format(op_result.fun))
print('theta: {}'.format(op_result.x))

# converting theta_history into J_history
J_history = (np.array(theta_history[::-1]) @ op_result.x)

# plot J_history
fig1, ax1 = plt.subplots()
ax1.plot(range(J_history.size), J_history)
ax1.set_xlabel('Iterations')
ax1.set_ylabel('Cost')

theta = op_result.x[:, np.newaxis]
plot_decision_boundary(theta=theta, X=X, y=y, hypothesis=sigmoid, precision=0.1, fig=fig, ax=ax, feature_map=(map_feature, 6))

# ============== Part 4: Predict and Accuracies ==============
# Compute accuracy on our training set
p = predict(X, theta)

print('Train Accuracy: {}'.format(np.mean(p == y) * 100))
print('Expected accuracy (with lambda = 1): 83.1 (approx)')

# ===============End================
plt.ioff()
plt.show()


import numpy as np

def base_test():
    arr = np.array([[1, 2, 3], [4, 5, 6]], dtype=int)
    print('矩阵:', arr)  # 矩阵
    print('类型:', arr.dtype)  # 类型
    print('维数:', arr.ndim)  # 维数
    print('行数/列数:', arr.shape)  # 行数/列数
    print('元素个数:', arr.size)  # 元素个数

    arr = np.zeros((3, 4))  # 所有元素为0的矩阵
    print('所有元素为0:', arr)
    arr = np.ones((3, 4), dtype=int)  # 所有元素为1的矩阵
    print('所有元素为1:', arr)
    arr = np.empty((3, 4))  # 所有元素近似于0的矩阵
    print('所有元素近似于0:', arr)
    arr = np.arange(10, 20, 2)  # 按步长生成范围数
    print('按步长生成范围数:', arr)
    arr = np.arange(12).reshape((3, 4))  # 生成12范围数并按3行4列排
    print('生成12范围数并按3行4列排:', arr)
    arr = np.linspace(10, 20, 2).reshape((2, 1))  # 从start开始到end结束的范围内生成num个数,可以reshape
    print('生成num个数:', arr)

def add_and_so_on():
    a = np.array([10, 20, 30, 40])  # 加减乘除直接算/乘并不是矩阵的乘法,而是单个相乘
    b = np.arange(4)
    print(a + b)

    print(b ** 2)  # 幂

    c = 10 * np.sin(a)  # sin
    print(c)

    print(b < 3)  # 结果为布尔值组成的列表

def dot_and_so_on():
    a = np.array([[10, 20], [30, 40]])
    b = np.arange(4).reshape((2, 2))
    # 矩阵乘法
    c = np.dot(a, b)  # 第一种方式
    print('乘法第一式:', c)
    d = a.dot(b)  # 第二种方式
    print('乘法第二式:', d)

    a = np.random.random((2, 4))  # 随机生成0-1的数并组成矩阵
    print(a)
    a = np.arange(14, 2, -1).reshape((3, 4))
    print('最大值:', np.max(a, axis=0))  # 最大值, axis: 1表示按行分组计算 0表示按列分组计算
    print('最大值索引:', np.argmax(a))  # 最大值下标
    print('最小值:', np.min(a, axis=1))  # 最小值
    print('最小值索引:', np.argmin(a))  # 最小值下标
    print('总和:', np.sum(a, axis=0))  # 总和
    print('平均值:', np.mean(a, axis=0))  # 平均值第一式
    print('平均值:', a.mean())  # 平均值第二式
    print('中位数:', np.median(a))  # 中位数
    print('逐步累加:', np.cumsum(a))  # 逐步累加生成列表
    print('相邻差:', np.diff(a))  # 每行中两两之差
    print('排序:', np.sort(a))  # 排序
    print('转置:', np.transpose(a))  # 转置第一式
    print('转置:', a.T)  # 转置第二式
    print('归数:', np.clip(a, 5, 9))  # 小于5的都等于5,大于9的都等于9
    print('下标取值:', a[1][2])  # 下标索引取值
    print('步长取值:', a[1, 0:2])  # 步长索引取值
    for raw in a:  # 行迭代
        print(raw)
    for column in a.T:  # 列迭代
        print(column)
    print(a.flatten())  # 矩阵变为一行
    for item in a.flat:  # 矩阵变为一行的迭代器
        print(item)

def merge_test():
    """合并"""
    A = np.array([1, 1, 1])
    B = np.array([2, 2, 2])
    C = np.vstack((A, B))  # 上下合并
    D = np.hstack((A, B))  # 左右合并
    print(C, C.shape)
    print(D, D.shape)
    A = A[:, np.newaxis]  # 冒号在前行上加维/冒号在后列上加维
    B = B[:, np.newaxis]
    print(np.vstack((A, B)))
    print(np.hstack((A, B)))
    print(np.concatenate((A, B, A, B), axis=1))  # axis: 1合并成行/左右合并 0合并成列/上下合并

def Segmentation_test():
    """分割"""
    A = np.arange(12).reshape(3,4)
    print(np.split(A, indices_or_sections=2, axis=1))  # 等项分割(分割块数需要合理)axis: 1按列分2块 0按行分2块
    print(np.array_split(A, 3,axis=1))  # 不等项分割,可以把4列按列分成3块,第一块2列,其他一列
    print(np.vsplit(A,3))  # 按行分割/上下分割
    print(np.hsplit(A,2))  # 按列分割/左右分割

def copy_test():
    a = np.arange(4)
    b = a
    c = a
    d = b
    print(b is a, c is a, d is a)
    # 上面四个全是a,改变任意一个,四个都会发生改变

    e = a.copy()
    print(e is a)
    # 使用copy方法,实际是deepcopy,e - a 互不影响

if __name__ == '__main__':
    base_test()
    # add_and_so_on()
    dot_and_so_on()
    # merge_test()
    # Segmentation_test()
    # copy_test()


"""
General purpose math functions, mostly geometric in nature.
"""

import math

import numpy as np
from numpy.linalg import norm
from scipy.linalg import svd

from aspire.utils.random import Random

def cart2pol(x, y):
    """
    Convert Cartesian to Polar Coordinates. All input arguments must be the same shape.
    :param x: x-coordinate in Cartesian space
    :param y: y-coordinate in Cartesian space
    :return: A 2-tuple of values:
        theta: angular coordinate/azimuth
        r: radial distance from origin
    """
    return np.arctan2(y, x), np.hypot(x, y)

def cart2sph(x, y, z):
    """
    Transform cartesian coordinates to spherical. All input arguments must be the same shape.

    :param x: X-values of input co-ordinates.
    :param y: Y-values of input co-ordinates.
    :param z: Z-values of input co-ordinates.
    :return: A 3-tuple of values, all of the same shape as the inputs.
        (<azimuth>, <elevation>, <radius>)
    azimuth and elevation are returned in radians.

    This function is equivalent to MATLAB's cart2sph function.
    """
    hxy = np.hypot(x, y)
    r = np.hypot(hxy, z)
    el = np.arctan2(z, hxy)
    az = np.arctan2(y, x)
    return az, el, r

def _mgrid_slice(n, shifted, normalized):
    """
    Util to generate a `slice` representing a 1d linspace
    as expected by `np.mgrid`.

    :param shifted: shifted by half of grid or not when n is even.
    :param normalized: normalize the grid in the range of (-1, 1) or not.
    :return: `slice` to be used by `np.mgrid`.
    """

    num_points = n * 1j
    start = -n // 2 + 1
    end = n // 2

    if shifted and n % 2 == 0:
        start -= 1 / 2
        end -= 1 / 2
    elif n % 2 == 0:
        start -= 1
        end -= 1

    if normalized:
        # Compute the denominator for normalization
        denom = n / 2
        if shifted and n % 2 == 0:
            denom -= 1 / 2

        # Apply the normalization
        start /= denom
        end /= denom

    return slice(start, end, num_points)

def grid_1d(n, shifted=False, normalized=True, dtype=np.float32):
    """
    Generate one dimensional grid.

    :param n: the number of grid points.
    :param shifted: shifted by half of grid or not when n is even.
    :param normalized: normalize the grid in the range of (-1, 1) or not.
    :return: the rectangular and polar coordinates of all grid points.
    """

    r = x = np.mgrid[_mgrid_slice(n, shifted, normalized)].astype(dtype)

    return {"x": x, "r": r}

def grid_2d(n, shifted=False, normalized=True, indexing="yx", dtype=np.float32):
    """
    Generate two dimensional grid.

    :param n: the number of grid points in each dimension.
    :param shifted: shifted by half of grid or not when n is even.
    :param normalized: normalize the grid in the range of (-1, 1) or not.
    :param indexing: 'yx' (C) or 'xy' (F), defaulting to 'yx'.
    See https://numpy.org/doc/stable/reference/generated/numpy.meshgrid.html
    :return: the rectangular and polar coordinates of all grid points.
    """

    grid = _mgrid_slice(n, shifted, normalized)
    y, x = np.mgrid[grid, grid].astype(dtype)
    if indexing == "xy":
        x, y = y, x
    elif indexing != "yx":
        raise RuntimeError(
            f"grid_2d indexing {indexing} not supported." "  Try 'xy' or 'yx'"
        )

    phi, r = cart2pol(x, y)

    return {"x": x, "y": y, "phi": phi, "r": r}

def grid_3d(n, shifted=False, normalized=True, indexing="zyx", dtype=np.float32):
    """
    Generate three dimensional grid.

    :param n: the number of grid points in each dimension.
    :param shifted: shifted by half of grid or not when n is even.
    :param normalized: normalize the grid in the range of (-1, 1) or not.
    :param indexing: 'zyx' (C) or 'xyz' (F), defaulting to 'zyx'.
    See https://numpy.org/doc/stable/reference/generated/numpy.meshgrid.html
    :return: the rectangular and spherical coordinates of all grid points.
    """

    grid = _mgrid_slice(n, shifted, normalized)
    z, y, x = np.mgrid[grid, grid, grid].astype(dtype)

    if indexing == "xyz":
        x, y, z = z, y, x
    elif indexing != "zyx":
        raise RuntimeError(
            f"grid_3d indexing {indexing} not supported." "  Try 'xyz' or 'zyx'"
        )

    phi, theta, r = cart2sph(x, y, z)

    # TODO: Should this theta adjustment be moved inside cart2sph?
    theta = np.pi / 2 - theta

    return {"x": x, "y": y, "z": z, "phi": phi, "theta": theta, "r": r}

def uniform_random_angles(n, seed=None, dtype=np.float32):
    """
    Generate random 3D rotation angles
    :param n: The number of rotation angles to generate
    :param seed: Random integer seed to use. If None, the current random state is used.
    :return: A n-by-3 ndarray of rotation angles
    """
    # Generate random rotation angles, in radians
    with Random(seed):
        angles = np.column_stack(
            (
                np.random.random(n) * 2 * np.pi,
                np.arccos(2 * np.random.random(n) - 1),
                np.random.random(n) * 2 * np.pi,
            )
        )
    return angles.astype(dtype)

def register_rotations(rots, rots_ref):
    """
    Register estimated orientations to reference ones.

    Finds the orthogonal transformation that best aligns the estimated rotations
    to the reference rotations.

    :param rots: The rotations to be aligned in the form of a n-by-3-by-3 array.
    :param rots_ref: The reference rotations to which we would like to align in
        the form of a n-by-3-by-3 array.
    :return: o_mat, optimal orthogonal 3x3 matrix to align the two sets;
            flag, flag==1 then J conjugacy is required and 0 is not.
    """

    assert (
        rots.shape == rots_ref.shape
    ), "Two sets of rotations must have same dimensions."
    K = rots.shape[0]

    # Reflection matrix
    J = np.array([[1, 0, 0], [0, 1, 0], [0, 0, -1]])

    Q1 = np.zeros((3, 3), dtype=rots.dtype)
    Q2 = np.zeros((3, 3), dtype=rots.dtype)

    for k in range(K):
        R = rots[k, :, :]
        Rref = rots_ref[k, :, :]
        Q1 = Q1 + R @ Rref.T
        Q2 = Q2 + (J @ R @ J) @ Rref.T

    # Compute the two possible orthogonal matrices which register the
    # estimated rotations to the true ones.
    Q1 = Q1 / K
    Q2 = Q2 / K

    # We are registering one set of rotations (the estimated ones) to
    # another set of rotations (the true ones). Thus, the transformation
    # matrix between the two sets of rotations should be orthogonal. This
    # matrix is either Q1 if we recover the non-reflected solution, or Q2,
    # if we got the reflected one. In any case, one of them should be
    # orthogonal.

    err1 = norm(Q1 @ Q1.T - np.eye(3, dtype=rots.dtype), ord="fro")
    err2 = norm(Q2 @ Q2.T - np.eye(3, dtype=rots.dtype), ord="fro")

    # In any case, enforce the registering matrix O to be a rotation.
    if err1 < err2:
        # Use Q1 as the registering matrix
        U, _, V = svd(Q1)
        flag = 0
    else:
        # Use Q2 as the registering matrix
        U, _, V = svd(Q2)
        flag = 1

    Q_mat = U @ V

    return Q_mat, flag

def get_aligned_rotations(rots, Q_mat, flag):
    """
    Get aligned rotation matrices to reference ones.

    Calculated aligned rotation matrices from the orthogonal transformation
    that best aligns the estimated rotations to the reference rotations.

    :param rots: The reference rotations to which we would like to align in
        the form of a n-by-3-by-3 array.
    :param Q_mat:  optimal orthogonal 3x3 transformation matrix
    :param flag:  flag==1 then J conjugacy is required and 0 is not
    :return: regrot, aligned rotation matrices
    """

    K = rots.shape[0]

    # Reflection matrix
    J = np.array([[1, 0, 0], [0, 1, 0], [0, 0, -1]])

    regrot = np.zeros_like(rots)
    for k in range(K):
        R = rots[k, :, :]
        if flag == 1:
            R = J @ R @ J
        regrot[k, :, :] = Q_mat.T @ R

    return regrot

def get_rots_mse(rots_reg, rots_ref):
    """
    Calculate MSE between the estimated orientations to reference ones.

    :param rots_reg: The estimated rotations after alignment in the form of
        a n-by-3-by-3 array.
    :param rots_ref: The reference rotations.
    :return: The MSE value between two sets of rotations.
    """
    assert (
        rots_reg.shape == rots_ref.shape
    ), "Two sets of rotations must have same dimensions."
    K = rots_reg.shape[0]

    diff = np.zeros(K)
    mse = 0
    for k in range(K):
        diff[k] = norm(rots_reg[k, :, :] - rots_ref[k, :, :], ord="fro")
        mse += diff[k] ** 2
    mse = mse / K
    return mse

def common_line_from_rots(r1, r2, ell):
    """
    Compute the common line induced by rotation matrices r1 and r2.

    :param r1: The first rotation matrix of 3-by-3 array.
    :param r2: The second rotation matrix of 3-by-3 array.
    :param ell: The total number of common lines.
    :return: The common line indices for both first and second rotations.
    """

    assert r1.dtype == r2.dtype, "Ambiguous dtypes"

    ut = np.dot(r2, r1.T)
    alpha_ij = np.arctan2(ut[2, 0], -ut[2, 1]) + np.pi
    alpha_ji = np.arctan2(ut[0, 2], -ut[1, 2]) + np.pi

    ell_ij = alpha_ij * ell / (2 * np.pi)
    ell_ji = alpha_ji * ell / (2 * np.pi)

    ell_ij = int(np.mod(np.round(ell_ij), ell))
    ell_ji = int(np.mod(np.round(ell_ji), ell))

    return ell_ij, ell_ji

def crop_pad_2d(im, size, fill_value=0):
    """
    :param im: A 2-dimensional numpy array
    :param size: Integer size of cropped/padded output
    :return: A numpy array of shape (size, size)
    """

    im_y, im_x = im.shape
    # shift terms
    start_x = math.floor(im_x / 2) - math.floor(size / 2)
    start_y = math.floor(im_y / 2) - math.floor(size / 2)

    # cropping
    if size <= min(im_y, im_x):
        return im[start_y : start_y + size, start_x : start_x + size]
    # padding
    elif size >= max(im_y, im_x):
        # ensure that we return in the same dtype as the input
        to_return = fill_value * np.ones((size, size), dtype=im.dtype)
        # when padding, start_x and start_y are negative since size is larger
        # than im_x and im_y; the below line calculates where the original image
        # is placed in relation to the (now-larger) box size
        to_return[-start_y : im_y - start_y, -start_x : im_x - start_x] = im
        return to_return
    else:
        # target size is between mat_x and mat_y
        raise ValueError("Cannot crop and pad an image at the same time.")


#
# MIT License
#
# Copyright (c) 2018 Jonathan Shore
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#

import numpy as np

class LaplaceDistribution:

    def __init__(self, mu: float, beta: float):
        self.mu = mu
        self.beta = beta

    def f(self, x):
        """
        density function

        :param x: value on domain or an array of values
        :return:
        """
        return 1 / (2*self.beta) * np.exp(-np.abs(x - self.mu) / self.beta)

    def logf(self, x):
        """
        Log density function

        :param x: value on domain or an array of values
        :return:
        """
        beta = self.beta
        return -(np.abs(x - self.mu) + beta * np.log(2 * beta)) / beta

    def cum(self, x0: float, x1: float):
        """
        cumulative density function
        """
        mu = self.mu
        beta = self.beta

        if x0 <= self.mu:
            cdf1 = 0.5 * np.exp((x0 - mu) / beta)
        else:
            cdf1 = 1 - 0.5 * np.exp(-(x0 - mu) / beta)

        if x1 <= self.mu:
            cdf1 = 0.5 * np.exp((x1 - mu) / beta)
        else:
            cdf1 = 1 - 0.5 * np.exp(-(x1 - mu) / beta)


# # Ejercicio _colabirativo_

#cambios introducidos 25/01
import numpy as np

# **Ejercicio 1**: Escribir un arreglo con 100 números equiespaciados del 0 al 9. Pista: `linspace`

np.linspace(0,9,100)

# **Ejercicio 2:** crear un arreglo 1D de 20 ceros.
# Reemplazar los primeros 15 elementos por unos.

arr = np.zeros(20)
nuevo = np.ones(15)
arr[:15] = nuevo
arr

# **Ejercicio 3:** crear un arreglo 1D de 50 ceros.
# Reemplazar los primeros 25 elementos por los números naturales del 0 al 24.

arr = np.zeros(50)
new = np.arange(25)
arr[:25] = new
arr

# **Ejercicio 4:** crear un arreglo 2D de 3 filas y 3 columnas, lleno de ceros.
# Reemplazar los elemento de la segunda columna por los números 1, 2 y 3 respectivamente.
# Es decir, crear la siguiente matriz:
#
# ```
# 0 1 0
# 0 2 0
# 0 3 0
# ```

arr = np.zeros((3,3))
arr[:,1] = [1,2,3]
arr

# **Ejercicio 5:** crear un arreglo 2D de 3 filas y 3 columnas, lleno de ceros.
# Reemplazar los elemento de la diagonal por unos. Es decir, crear la siguiente matriz:
#
# ```
# 1 0 0
# 0 1 0
# 0 0 1
# ```

arr = np.zeros((3,3))
for i in range(3):
    arr[i,i] = 1

# **Ejercicio 6:** crear un arreglo 2D de 100 filas y 100 columnas, lleno de ceros.
# Reemplazar los elemento de la diagonal por unos. Es decir, crear la siguiente matriz:
#
# ```
# 1 0 0 ... 0 0 0
# 0 1 0 ... 0 0 0
# 0 0 1 ... 0 0 0
# ...
# 0 0 0 ... 1 0 0
# 0 0 0 ... 0 1 0
# 0 0 0 ... 0 0 1
# ```

arr = np.zeros((100,100))
arr = np.eye(100)
arr


import numpy as np
import pandas as pd
def classify_prices(discount):
	price_classification = [] # Change/remove this line
	for d in discount:
		if float(d) <= 0:
			category = 'no_discount'
			price_classification.append(category)
		elif 0 <= float(d) <= 0.1:
			category = 'discounted'
			price_classification.append(category)
		elif 0.1 <= float(d) <= 0.2:
			category = 'good_deal'
			price_classification.append(category)
		else:
			category = 'buy_now'
			price_classification.append(category)
	# Please, introduce your answer here
	return price_classification

def calculate_discount(current, reference):
	list_discount = []
	for i in range(len(current)):
		c = current[i]
		r = reference[i]
		discount = (r - c)/r
		list_discount.append(discount)

	return list_discount

def read_files(current_price_filename, reference_price_filename):
	with open(current_price_filename,encoding='utf-8')as f:
		data = np.loadtxt(f,delimiter=',')

	with open(reference_price_filename, encoding='utf-8')as f:
		data1 = np.loadtxt(f, delimiter=',')

	current = np.array(data,dtype=np.int)  # Change/remove this line
	reference = np.array(data1,dtype=np.int)  # Change/remove this line
	# Please, introduce your answer here

	return current, reference

def check_output(current, reference, discount, price_classification):
	# Do not modify this function, it is provided only for you to check your answer
	n_prices = len(discount)
	print('----------------------------------------------')
	print('P', 'current', 'ref', 'discount', 'classification', sep='\t')
	print('----------------------------------------------')
	for i in range(n_prices):
		print(i, current[i],
			  reference[i],
			  str(np.round(discount[i], 2)) + '%',
			  price_classification[i], sep='\t')

if __name__ == '__main__':
	current_price_filename = 'data/current_prices_example.csv' # You can change this value for testing
	reference_price_filename = 'data/reference_prices_example.csv' # You can change this value for testing

	# The lines below are provided to run your code in a similar order as
	# will be done during marking and to help you check your answer.
	current, reference = read_files(current_price_filename, reference_price_filename)
	discount = calculate_discount(current, reference)
	price_classification = classify_prices(discount)

	# You can use the function below to check your answer only
	# Please comment it for your submission
	check_output(current, reference, discount, price_classification)


from scipy.optimize import linprog
import numpy as np

# Objective function
z = np.array([300,500,200])
expense = 75000

# Constraints
C = np.array([
    [ 10, 7.5,   4],        #C1
    [  0,  10,   0],        #C2
    [0.5, 0.4, 0.5],        #C3
    [  0, 0.4,   0],        #C4
    [0.5, 0.1, 0.5],        #C5
    [0.4, 0.2, 0.4],        #C6
    [  1, 1.5, 0.5],        #C7
    [  1,   0,   0],        #C8
    [  0,   1,   0],        #C9
    [  0,   0,   1]         #C10
])

b = np.array([4350, 2500, 280, 140, 280, 140, 700, 300, 180, 400])

# Bounds
x1 = (0, None)
x2 = (0, None)
x3 = (0, None)

#Solution
sol = linprog(-z, A_ub = C, b_ub = b, bounds = (x1, x2, x3), method='simplex')

#Profit Monthly.
profit = (sol.fun*-1) - expense

print(f"x1 = {sol.x[0]}, x2 = {sol.x[1]}, x3 = {sol.x[2]}, z = {profit}")


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

# Cost function
def cost(m, x, y, z):
	err=0.0
	for i in range(0, m):
		err += ((hypothesis(i, x, z) - y[i])**2)
	err = err/(2*m)
	return float(err)

# Delivetive of cost function by theta0
def find_local_minimum_theta0(m, _input, output, theta_array):
	err=0.0
	for i in range(0, m):
		err += (hypothesis(i, _input, theta_array) - output[i])
	err = err/m
	return float(err)

# Delivetive of cost function by theta1
def find_local_minimum_theta1(m, _input, output, theta_array):
	err=0.0
	for i in range(0, m):
		err += (hypothesis(i, _input, theta_array) - output[i])*_input[i]
	err = err/m
	return float(err)

# Hypothesis
def hypothesis(i, x, z):
	h =  z[0]*1+z[1]*x[i]
	return h

# Update theta by Gradient Descent
# Define theta0 as z0
# Define theta1 as z1
def find_local_minimum_theta(alpha, theta0, theta1, m, _input, output):
	z0 = theta0
	z1 = theta1
	t_z0 = 0.0
	t_z1 = 0.0
	r = 1

	while 1 :
		print "===== Round %d =====" %(r)
		z = np.array([z0, z1])
		t_z0 = t_z0 - alpha * find_local_minimum_theta0(m, _input, output, z)
		t_z1 = t_z1 - alpha * find_local_minimum_theta1(m, _input, output, z)
		if z0 == t_z0 and z1 == t_z1 :
			break
		else:
			print " -> update thata0 from %.8f to %.8f" %(z0, t_z0)
			print " -> update thata1 from %.8f to %.8f" %(z1, t_z1)
			# Update Thata
			z0 = t_z0
			z1 = t_z1
		r += 1
	return np.array([z0,z1])

# Generate linear function
def graph_gen(low, high, size):
	g=np.arange(size, dtype=float)
	for i in range(0 , size):
		g[i] = i + random.uniform(low,high)
	return g

# Input used for tranning
#x=np.array([0,1,2,3,4,5])
x=np.arange(100,dtype=float)

# Output used for tranning
#y=np.array([0,1,2,3,4,5])
#y=np.random.normal(5,1,100)
y=graph_gen(0,5,100)

# Initiaize theta
z=np.array([0,0])

# Range of theta value
theta_range=50

# Size of rows or Columns
theta_sz=2*theta_range+1 #1 for including 0 value

# Number of input elements
m=x.size

# Results of Squared Error
result_squared_err = np.ones(((2*theta_range)+1, (2*theta_range)+1), dtype=float)

# Leaning Rate
alpha = 0.00055

# Run Gradient Descent
theta_array = find_local_minimum_theta(alpha, 0.0, 0.0, m, x, y)
print "========================="
print "Gradient Descent : %f    " %(cost(m,x,y,theta_array))
print "========================="

# Plot original data
plt.plot(x,y,'rs')

# Plot linear regression function
x_grph=np.arange(m);
plt.plot(x_grph, theta_array[0]+x_grph*(theta_array[1]), 'b-')

# Display Graph
#plt.axis([0.,100.,0.,100.])
plt.show()


from numpy import *
from matplotlib.pyplot import *

def f(beta):
    return cosh(beta)*cos(beta) + 1

def damped(beta):
    """Damp the amplitude of f. It grows like cosh, i.e. exp."""
    return exp(-beta)*f(beta)

def plot_f():
    beta = linspace(0, 20, 501)
    #y = f(x)
    y = damped(beta)
    plot(beta, y, 'r', [beta[0], beta[-1]], [0, 0], 'b--')
    grid('on')
    xlabel(r'$\beta$')
    ylabel(r'$e^{-\beta}(\cosh\beta\cos\beta +1)$')
    savefig('tmp1.png'); savefig('tmp1.pdf')
    show()

plot_f()

from nonlinear_solvers import bisection
# Set up suitable intervals
intervals = [[1, 3], [4, 6], [7, 9]]
betas = []  # roots
for beta_L, beta_R in intervals:
    beta, it = bisection(f, beta_L, beta_R, eps=1E-6)
    betas.append(beta)
    print f(beta)
print betas

# Find corresponding frequencies

def omega(beta, rho, A, E, I):
    return sqrt(beta**4/(rho*A/(E*I)))

rho = 7850  # kg/m^3
E = 1.0E+11 # Pa
b = 0.025   # m
h = 0.008   # m
A = b*h
I = b*h**3/12

for beta in betas:
    print omega(beta, rho, A, E, I)


import matplotlib.pyplot as plt
import numpy as np
from sklearn.linear_model import LinearRegression

def simple_example():
    X = [10, 20, 30]
    Y = [15, 19, 45]
    plt.scatter(X, Y,)
    plt.show()

    A = np.array([10, 1, 20, 1, 30, 1]).reshape(3, 2)
    B = np.array(Y).reshape(3, 1)

    a = np.linspace(10, 30)
    arr = np.matmul(np.matmul(np.linalg.inv(np.matmul(A.T, A)), A.T), Y)
    arr.tolist()
    beta, alpha = arr
    Yi = alpha + beta * a

    plt.scatter(X, Y)
    plt.plot(a, Yi)
    plt.show()

def linear_least_squares(examples):
    m, n = examples.shape
    cx = examples[0].reshape(n, 1)
    c2 = np.ones(len(cx)).reshape(n, 1)
    A = np.hstack((cx, c2))

    return np.matmul(np.matmul(np.linalg.inv(np.matmul(A.T, A)), A.T), examples[1])

def plot_figure(x, y, alpha, beta, title, x_label, y_label):
    min_y = alpha + beta * min(x)
    max_y = alpha + beta * max(x)

    plt.plot([min(x), max(x)], [min_y, max_y])
    plt.scatter(x, y, color='orange')
    plt.xlabel(x_label)
    plt.title(title)
    plt.grid(True)
    plt.ylabel(y_label)
    plt.show()

def plot_linear_regression(examples, title='Linear Least Squares Regression Example', x_label='X', y_label='Y'):
    min_x = min(examples[0])
    max_x = max(examples[0])
    theta = linear_least_squares(examples)
    theta.tolist()
    beta, alpha = theta

    min_y = alpha + beta * min_x
    max_y = alpha + beta * max_x

    plt.plot([min(examples[0]), max(examples[0])], [min_y, max_y])
    plt.scatter(examples[0], examples[1], color='orange')
    plt.xlabel(x_label)
    plt.ylabel(y_label)
    plt.title(title)
    plt.grid(True)
    plt.show()

def simple_linear_least_squares_example():
    plot_linear_regression(np.array([[1.5, 1.6, 1.3, 1.4, 1.5, 1.7, 1.8, 1.7, 1.1, 1.2], [10, 12, 16, 13, 15, 11, 8, 10, 18, 13]]), x_label='Prices', y_label='Sales')

def statistic_linear_regression(x, y):
    number_of_elements = len(x)
    if number_of_elements != len(y):
        raise Exception("Size of x and y must be equal!")
    mean_x, mean_y = sum(x)/number_of_elements, sum(y)/number_of_elements
    sum_x_vezes_y = sum([i * j for i, j in zip(x, y)])
    sum_x_pow_2 = sum([i ** 2 for i in x])
    sxy = sum_x_vezes_y - number_of_elements * mean_x * mean_y
    sxx = sum_x_pow_2 - number_of_elements * mean_x * mean_x
    beta = sxy / sxx
    alpha = mean_y - beta * mean_x
    return alpha, beta

def plot_statistic_linear_regression(x, y, title='Statistic Linear Regression Example', x_label='X', y_label='Y'):
    alpha, beta = statistic_linear_regression(x, y)
    plot_figure(x, y, alpha, beta, title, x_label, y_label)

def simple_statistic_linear_regression_example():
    plot_statistic_linear_regression([1.5, 1.6, 1.3, 1.4, 1.5, 1.7, 1.8, 1.7, 1.1, 1.2], [10, 12, 16, 13, 15, 11, 8, 10, 18, 13], x_label='Prices', y_label='Sales')

def sklearn_linear_regression(x, y):
    reg = LinearRegression().fit(x.reshape(-1, 1), y.reshape(-1, 1))
    return reg.intercept_[0], reg.coef_[0][0]

def plot_sklearn_linear_regression(x, y, title='Sklearn Linear Regression Example', x_label='X', y_label='Y'):
    alpha, beta = sklearn_linear_regression(x, y)
    plot_figure(x, y, alpha, beta, title, x_label, y_label)

def simple_sklearn_linear_regression_example():
    prices = np.array([1.5, 1.6, 1.3, 1.4, 1.5, 1.7, 1.8, 1.7, 1.1, 1.2])
    sales = np.array([10, 12, 16, 13, 15, 11, 8, 10, 18, 13])
    plot_sklearn_linear_regression(prices, sales, x_label='Prices', y_label='Sales')

if __name__ == '__main__':
    simple_linear_least_squares_example()
    simple_statistic_linear_regression_example()
    simple_sklearn_linear_regression_example()


import numpy as np
"""
    Implementation of the loss function

    Arguments:
    y_pred -- probability vector corresponding to your label predictions, shape (1, number of examples)
    Y -- true "label" vector (for example: containing 0 if non-cat, 1 if cat), shape (1, number of examples)

    Returns:
    loss

"""
# Loss function is used to monitor, how the model is performing.
# It is supposed to approach global optimum i.e. smallest value possible.

def logistic_loss(a3, Y):
    m = Y.shape[0]

    logprobs = np.multiply(-np.log(a3),Y) + np.multiply(-np.log(1 - a3), 1 - Y)
    cost = 1./m * np.sum(logprobs)

    return cost

def MAE(y_pred, y):
    cost = np.sum(np.abs(y_pred - y))/m
    return cost

def MSE(y_pred, y):
    cost = np.sum((y_pred - y)**2)/m
    return cost


import numpy as np
from scipy.interpolate import CubicSpline
from scipy import integrate

def arc_length(cubic_spline,parameterization:np.ndarray):
    """
    Parameters
    ----------
    cubic_spline : scipy.interpolate._cubic.CubicSpline
        Cubic spline object
    parameterization : numpy.ndarray
        Array of size N. Represents the parameterization values of the cubic spline.
        Must be monotonically increasing.
    Returns
    -------
    arclength : numpy.ndarray
        Array of size N.
    errs :  numpy.ndarray
        DESCRIPTION.
    """
    df = lambda t : np.sqrt(np.sum(cubic_spline.derivative()(t)**2)) # arc-length
    segments = len(parameterization)-1
    sub_arclength = np.zeros((segments,))
    errs = np.zeros((segments,))
    for i in range(segments):
        subf,suberr = integrate.quad(df,parameterization[i],parameterization[i+1])
        sub_arclength[i] = subf
        errs[i] = suberr
    arclength = np.hstack((0,sub_arclength.cumsum()))
    return arclength,errs

def alp_spline(xyz:np.ndarray):
    ppdist = np.sqrt(np.sum(np.diff(xyz)**2,axis=0)) # point to point distance

    non_zero_indices = ppdist>0
    ppdist = ppdist[non_zero_indices]

    xyz = xyz[:,np.hstack((True,non_zero_indices))]

    linear_dist = np.hstack((0,ppdist.cumsum()))
    ldp_cs = CubicSpline(linear_dist,np.transpose(xyz))

    arclength,errs = arc_length(ldp_cs,linear_dist)
    alp_cs = CubicSpline(arclength,np.transpose(xyz))
    return linear_dist,ldp_cs,arclength,alp_cs


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sun Mar 10 16:23:09 2019

@author: alankar
"""

import numpy as np
#import matplotlib.pyplot as plt

distance = lambda x:np.dot(x,x.T)

dimension = 10
N = int(1e4)
x = np.random.uniform(low=-1,high=1,size=(N,dimension))
length = np.diag(distance(x))
f = np.piecewise(length,[length<=1.],[1.,0.])
I = (2**dimension/N)*np.sum(f)
varf = (1/N)*np.sum(f**2)-(I/2**dimension)**2
error = (2**dimension)*np.sqrt(varf/N)
print('Volume of a unit sphere in %d dimension: %f'%(dimension,I))
print('Error in the estimate: %f'%error)

"""
Output:

Volume of a unit sphere in 10 dimension: 2.150400
Error in the estimate: 0.468763
"""


import numpy as np

def simpson_formula(inte, func):
    """ Calculate integral of function func on interval [inte[0], inte[1]].

    Args:
        inte: list/ndarray, the intergration interval
        func: function object, the intergrand

    Returns:
        double, the integral value
    """
    x_lst = np.linspace(inte[0], inte[1], 3)
    # Simpson integral formula cofficients
    C = np.array([1, 4, 1])
    return (inte[1] - inte[0]) * np.sum(C @ func(x_lst)) / np.sum(C)

def adaptive_Simpson_formula(inte, func, tol=1e-9):
    """ Calculate integral of function func on interval[inte[0], inte[1]] with accuracy tol.

    Args:
        inte: list/ndarray, the intergration interval
        func: function, intergrand
        tol: double, accuracy of the integral value

    Returns:
        double, integral value
    """
    # Simpson formula
    S1 = simpson_formula(inte, func)
    S2 = simpson_formula([inte[0], sum(inte)/2], func)
    S3 = simpson_formula([sum(inte)/2, inte[1]], func)

    if np.abs(S1 - S2 - S3) >= 10 * tol:
        S2 = adaptive_Simpson_formula([inte[0], sum(inte)/2], func, 5 * tol)
        S3 = adaptive_Simpson_formula([sum(inte)/2, inte[1]], func, 5 * tol)

    return S2 + S3

def f(x):
    return np.exp(-1 * x**2)

def g(x):
    return np.sin(x) / x

if __name__ == '__main__':
    # integration interval
    inte = [1e-32, 1]
    # adaptive Simpson formula
    x1 = adaptive_Simpson_formula(inte, f)
    x2 = adaptive_Simpson_formula(inte, g)
    print(f"The first integral' value is {x1:.7f} by adaptive Simpson formula.")
    print(f"The second integral's value is {x2:.7f} by adaptive Simpson formula.")