import numpy as np

def create_rank_k_dataset(
        n_rows=5,
        n_cols=5,
        k=3,
        fraction_missing=0.1,
        symmetric=False,
        random_seed=0):
    np.random.seed(random_seed)
    x = np.random.randn(n_rows, k)
    y = np.random.randn(k, n_cols)

    XY = np.dot(x, y)

    if symmetric:
        assert n_rows == n_cols
        XY = 0.5 * XY + 0.5 * XY.T

    missing_raw_values = np.random.uniform(0, 1, (n_rows, n_cols))
    missing_mask = missing_raw_values < fraction_missing

    XY_incomplete = XY.copy()
    # fill missing entries with NaN
    XY_incomplete[missing_mask] = np.nan

    return XY, XY_incomplete, missing_mask

# create some default data to be shared across tests
XY, XY_incomplete, missing_mask = create_rank_k_dataset(
    n_rows=500,
    n_cols=10,
    k=3,
    fraction_missing=0.25)


import numpy as np

from scipy.signal import find_peaks_cwt

def get_maxima_large(value_list):
    '''
    value_list is list from which to determine maxima
    maxima are True values
    returns list [<boolean>,<boolean>]
    '''
    cb = np.array(value_list)
    indexes = find_peaks_cwt(cb, np.arange(1, 10))  # ?????

    # create list as long as value_list initialized to False or not a maxima

    maxima = [False] * len(value_list)

    for i in indexes:
        maxima[i] = True
        if i > 0 and value_list[i - 1] > value_list[i]:  # this is a work around for a bad maxima
            # print('fix: ',i)
            maxima[i] = False
            maxima[i - 1] = True
            # print(i, 'maxima',value_list[i])

    return maxima

# test
value_test = [1.0, 3.0, 5.0, 10.0, 4.0, 3.0, 1.0]
expected_list = [False, False, False, True, False, False, False]
result_list = get_maxima_large(value_test)
assert expected_list == result_list


# Polynomial Regression

# Importing libraries

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

# Importing dataset
dataset = pd.read_csv('Position_Salaries.csv')

# pd.set_option('display.float_format', lambda x: '%.0f' % x)

# matrix of features (independent variables)
X = dataset.iloc[:, 1:2].values
# dependant variable vector
y = dataset.iloc[:, -1].values

# Fitting Linear regression
from sklearn.linear_model import LinearRegression

linear_regressor = LinearRegression()
linear_regressor.fit(X, y)

# Fitting Polynomial Regression
from sklearn.preprocessing import PolynomialFeatures

poly_regressor = PolynomialFeatures(degree = 4)
X_poly = poly_regressor.fit_transform(X)

lin_poly_reg = LinearRegression()
lin_poly_reg.fit(X_poly, y)

# Visualize the results
# 1.
plt.scatter(X, y, color = 'red')
plt.plot(X, linear_regressor.predict(X), color = 'green')
plt.title('Linear Regression plot')
plt.xlabel('Position level')
plt.ylabel('Salary')

# 2.
X_grid = np.arange(min(X), max(X), 0.1)
X_grid = X_grid.reshape((len(X_grid), 1))
plt.scatter(X, y, color = 'red')
plt.plot(X_grid, lin_poly_reg.predict(poly_regressor.fit_transform(X_grid)), color = 'green')
plt.title('Polynomial Regression plot')
plt.xlabel('Position level')
plt.ylabel('Salary')

# Predicting new results

# with Linear Regression
linear_regressor.predict(6.5)

# with Polynomial Regression
lin_poly_reg.predict(poly_regressor.fit_transform(6.5))


import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
#Scipy库中的optimiz可以实现matlab中fminunc的功能，来优化函数计算成本和梯度
import scipy.optimize as opt
#高级处理分类的一个信息report
from sklearn.metrics import classification_report as cr
#=================visualizing data

path = 'E:\lessons\ML wu.n.g\coursera-ml-py-master\coursera-ml-py-master\machine-learning-ex2\ex2\ex2data1.txt'
data = pd.read_csv(path, names=['ex1score', 'ex2score', 'admitted'])
print(data.head(),data.describe())
#dataframe有布尔筛选功能 ，筛选出符合条件的数据
#isin可以进行布尔判断该属性的值是否符合isin的内容
positive = data[data.admitted.isin(['1'])]
negetive = data[data.admitted.isin(['0'])]
fig, ax = plt.subplots(figsize=(8,8))
ax.scatter(positive['ex1score'],positive['ex2score'], c='b', label = 'Admitted')
ax.scatter(negetive['ex1score'],negetive['ex2score'],c='r', s=50, marker='x', label = 'Failed')
#获取轴的位置
pos = ax.get_position()
#设置轴的新位置（left，bottom，width，heigeth）
ax.set_position([pos.x0, pos.y0, pos.width, pos.height * 0.8])
#设置图例在图的上方外侧 bbox_to_anchor:表示legend位置，前一个左右后上下，使用后
#loc将不再起正常作用； ncol = 3 表示图例的几列显示
#该句写法其实是原作者通过试探得来的参数。。。。
ax.legend(loc = 'center left', bbox_to_anchor=(0.3, 1.12), ncol = 3)
ax.set_xlabel('Exam 1 Score')
ax.set_ylabel('Exam 2 Score')
#plt.show()

#=================sigmoid function

def sigmoid(z):
    return 1 / (1 + np.exp(-z))
'''画出sigmoid函数
x1 = np.arange(-10, 10, 0.1)
plt.plot(x1, sigmoid(x1),c = 'r')
plt.show()
'''

#================cost function

def cost(theta , X, Y):
    first = (-Y) * np.log(sigmoid(X @ theta))
    second = (1 - Y) * np.log(1 - sigmoid(X @ theta))
    return np.mean(first - second)
#初始化数据
if  'Ones' not in data.columns:
     data.insert(0, 'Ones', 1)
#这里写法与ex1不同，此时将X和Y转换成了Numpy - array而不是matrix
X = data.iloc[:, :-1].as_matrix()
Y = data.iloc[:,-1].as_matrix().reshape(-1)
theta = np.zeros(X.shape[1]).T
#print(cost(theta, X ,Y))

#==================Gradient descent

def gradient(theta, x, y):
     return (x.T @ (sigmoid(x @ theta) -y)) / len(y)
#print(gradient(theta, X, Y))
#使用高级优化函数optimize来运算速度远远超过梯度下降，只需传入cost函数、theta和梯度
#注意在使用时cost函数定义theta要放在第一个
#算法有很多种类这里选用fimin_tnc（Newton Conjugate-Gradient）
result = opt.fmin_tnc(func = cost, x0 =theta ,fprime = gradient, args=(X,Y))
#返回array解决方案；迭代次数；一个XX编码
#print(result)
#res = opt.minimize(fun=cost, x0=theta, args=(X, y), method='TNC', jac=gradient)
#以上为另一种方法，minimize可以选择更多方法
#print("final_cost = ", cost(result[0], X, Y))

#==================Using model to predtict

def predict(theta, X):
     probability = sigmoid(X @ theta)
     return [1 if x >= 0.5 else 0 for x in probability]
final_theta = result[0]
#print('predictions=' ,predict(final_theta, X))
predictions = predict(final_theta, X)
#zip()函数，参数是迭代对象，作用将相同位置的元素打包成一个个的tuple
correct = [1 if a==b else 0 for (a,b) in zip(predictions, Y)]
accuracy = sum(correct) / len(Y)
#print(accuracy)
#也可用sklearn中的方法进行检查
#print(cr(predictions,Y))

#==================Decision boundary

#X＠theta = 0
x1 = np.arange(0, 130, step =0.1)
x2 = -(final_theta[0] + x1 * final_theta[1]) / final_theta[2]
#绘图
fig, ax = plt.subplots(figsize = (8,8))
ax.scatter(positive['ex1score'], positive['ex2score'], c = 'b', label = 'Admitted')
ax.scatter(negetive['ex1score'], negetive['ex2score'], c = 'r', s = 50, marker = 'x', label= 'Failed')
#画初决策边界
ax.plot(x1, x2)
pos = ax.get_position()
#设置轴的新位置（left，bottom，width，heigeth）
ax.set_position([pos.x0, pos.y0, pos.width, pos.height * 0.8])
ax.legend(loc = 'center left', bbox_to_anchor=(0.3, 1.12), ncol = 3)
ax.set_xlabel('Exam 1 Score')
ax.set_ylabel('Exam 2 Score')
ax.set_title('Decision Boundary')
#plt.show()


import math as m
import numpy as np

from src.continuous.gamma import GammaDist
from src.discrete.poisson import PoissonDist
from src.prob_distribution import ProbDist
from src.spaces.spaces1d_leafs import DiscreteSpace

class NegBinDist(ProbDist):
    """Simple ngeative binomial distribution."""

    def __init__(self, r = 10, p = 0.5):
        """Create NegBin(r, p) distribution.

        :param r Which should be summed
        :param p Probability that random var is true
        """

        # save params
        assert 0 <= p <= 1
        assert 0 <= r
        self.r = r
        self.p = p

        # create distribution for sampling
        self.GG = GammaDist(r, p / (1 - p))
        self.PG = PoissonDist(0.1)
        super().__init__(DiscreteSpace(0, np.inf))

    def expectation(self):
        """Calculates the expectations for that distribution.

        :returns The expectation of the distribution"""

        r = self.r
        p = self.p
        return r * (1 - p) / p

    def var(self):
        """Calculates the variance for that distribution.

        :returns The variance of the distribution"""

        r = self.r
        p = self.p
        return r * (1 - p) / p ** 2

    def sample(self, num_samples = 1):
        """Generate random numbers from NegBin(r, p).

        :param num_samples How many random numbers should be generated.
        :returns Random numbers x ~ NegBin(r, p).
        """

        # a gamma generator and the result vector
        L = self.GG.sample(num_samples)
        X = np.empty(num_samples)

        # fill it up
        for k in range(len(X)):
            self.PG.rate = L[k]
            X[k] = self.PG.sample()

    def __density(self, x):
        """This method calculates the mass NegBin(r, p).

        :param x Which value should be evaluated.
        :returns The probability this element occurs.
        """

        r = self.r
        p = self.p
        prev = m.gamma(r + x) / (m.gamma(r) * m.factorial(x))
        return prev * p ** r * (1 - p) ** x


from mpl_toolkits.mplot3d import Axes3D    ##New Library required for projected 3d plots

import numpy
from matplotlib import pyplot, cm

###variable declarations
nx = 81
ny = 81
nt = 100
c = 1
dx = 2 / (nx - 1)
dy = 2 / (ny - 1)
sigma = .2
dt = sigma * dx

x = numpy.linspace(0, 2, nx)
y = numpy.linspace(0, 2, ny)

u = numpy.ones((ny, nx)) ##create a 1xn vector of 1's
un = numpy.ones((ny, nx)) ##

###Assign initial conditions

##set hat function I.C. : u(.5<=x<=1 && .5<=y<=1 ) is 2
u[int(.5 / dy):int(1 / dy + 1),int(.5 / dx):int(1 / dx + 1)] = 2

###Plot Initial Condition
##the figsize parameter can be used to produce different sized images
fig = pyplot.figure(figsize=(11, 7), dpi=100)
ax = fig.gca(projection='3d')
X, Y = numpy.meshgrid(x, y)
surf = ax.plot_surface(X, Y, u[:], cmap=cm.viridis)

u = numpy.ones((ny, nx))
u[int(.5 / dy):int(1 / dy + 1), int(.5 / dx):int(1 / dx + 1)] = 2

for n in range(nt + 1): ##loop across number of time steps
    un = u.copy()
    row, col = u.shape
    for j in range(1, row):
        for i in range(1, col):
            u[j, i] = (un[j, i] - (c * dt / dx * (un[j, i] - un[j, i - 1])) -
                                  (c * dt / dy * (un[j, i] - un[j - 1, i])))
            u[0, :] = 1
            u[-1, :] = 1
            u[:, 0] = 1
            u[:, -1] = 1

fig = pyplot.figure(figsize=(11, 7), dpi=100)
ax = fig.gca(projection='3d')
surf2 = ax.plot_surface(X, Y, u[:], cmap=cm.viridis)

"""
u = numpy.ones((ny, nx))
u[int(.5 / dy):int(1 / dy + 1), int(.5 / dx):int(1 / dx + 1)] = 2

for n in range(nt + 1): ##loop across number of time steps
    un = u.copy()
    u[1:, 1:] = (un[1:, 1:] - (c * dt / dx * (un[1:, 1:] - un[1:, :-1])) -
                              (c * dt / dy * (un[1:, 1:] - un[:-1, 1:])))
    u[0, :] = 1
    u[-1, :] = 1
    u[:, 0] = 1
    u[:, -1] = 1

fig = pyplot.figure(figsize=(11, 7), dpi=100)
ax = fig.gca(projection='3d')
surf2 = ax.plot_surface(X, Y, u[:], cmap=cm.viridis)
"""


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

from uncertify.visualization.plotting import setup_plt_figure

def plot_gauss_1d_kl_div(mean1, std1, mean2, std2, xmin: int = -10, xmax: int = 10, n_samples: int = 100) -> plt.Figure:
    """Plot two Gauss distributions (mean1, std1) and (mean2, std2) and calculate the KL divergence (figure title)."""
    def kl_divergence(p, q):
        return np.mean(np.where(p != 0, p * np.log(p / q), 0))

    x_values = np.linspace(xmin, xmax, n_samples)
    gauss_values_1 = norm.pdf(x_values, mean1, std1)
    gauss_values_2 = norm.pdf(x_values, mean2, std2)
    fig, ax = setup_plt_figure(title=f'KL(p||q) = {kl_divergence(gauss_values_1, gauss_values_2):1.3f}',
                               xlabel='x', ylabel='pdf(x)')
    ax.plot(x_values, gauss_values_1, 'o-', c='teal', label=f'p {mean1, std1}')
    ax.plot(x_values, gauss_values_2, 'o-', c='orange', label=f'q {mean2, std2}')
    ax.legend()
    return fig


# Problem: https://projecteuler.net/problem=131

"""
    . Let n, p, a be positive integers.
    . Let cbtr(x) be the cube root of x.
    . n^3 + p*n^2 = a^3
    So, n^3 * (n+p) / n = a^3
    Take the cuberoot of the two sides, we have,
        n * cbrt(n+p)/cbrt(n) = a
        Since n and a are positive integers, then cbrt(n+p)/cbrt(n) must be rational.
        So, n+p and n must be cubes.
        Let n+p = X^3, n = Y^3 for positive integers X, Y.
        Then p = X^3 - Y^3 = (X-Y)(X^2+XY+Y^2).
        Note that X^2+XY+Y^2 = (X-Y)^2 + 3XY > X - Y.
        Since p is prime, there are 2 cases:
            Case 1: X-Y = P and X^2+XY+Y^2 = 1
                This means X-Y > X^2 + XY + Y^2 (contradiction)
            Case 2: X-Y = 1 and X^2+XY+Y^2 = P
        So, X-Y = 1, or X = Y + 1.
    Also, p = X^3 - Y^3 = (Y+1)^3 - Y^3
    So, we can iterate through all Y and find whether (Y+1)^3 - Y^3 is a prime that is smaller than 10^6.
"""

from sage.all import is_prime

N = 1e6

ans = 0

Y = 0

while True:
    Y = Y + 1
    X = Y + 1
    p = X**3 - Y**3
    if p > N:
        break
    if is_prime(p):
        ans = ans + 1

print(ans)


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

x_max = 2           # Max domain in X
y_max = 1           # Max domain in Y
x_points = 50       # Number of grid points in X
y_points = 50       # Number of grid points in Y
it_points = 100     # Number of iteration points
del_x = x_max/float(x_points - 1)
del_y = y_max/float(y_points - 1)

x = np.linspace(0, x_max, x_points)
y = np.linspace(0, y_max, y_points)

p = np.zeros((x_points, y_points))  # Pressure = 0 at all points except boundary points
p[0,:] = 0       # Dirichlet boundary condition p = 0 at x = 0
p[-1,:] = 0      # Dirichlet boundary condition p = 0 at x = 2
p[:, 0] = 0     # Dirichlet boundary condition p = 0 at y = 0
p[:, -1] = 0    # Dirichlet boundary condition p = 0 at y = 1

b = np.zeros((x_points, y_points))      # RHS in Poisson's equation
b[x_points/4, y_points/4] = 100.0       # Spikes in b_ij
b[3*x_points/4, 3*y_points/4] = -100.0

# Loop through iterations
p_new = np.zeros((x_points, y_points))

for it in range(0, it_points):
    for ix in range(1, x_points - 1):
        for iy in range(1, y_points - 1):
            p_new[ix, iy] = (del_y ** 2 * (p[ix + 1, iy] + p[ix - 1, iy]) + del_x ** 2 * (
                        p[ix, iy + 1] + p[ix, iy - 1]) - (b[ix, iy] * del_x ** 2 * del_y ** 2)) / (
                                        float(2) * (del_x ** 2 + del_y ** 2))

            p[0, :] = 0  # Dirichlet boundary condition p = 0 at x = 0
            p[-1, :] = 0  # Dirichlet boundary condition p = 0 at x = 2
            p[:, 0] = 0  # Dirichlet boundary condition p = 0 at y = 0
            p[:, -1] = 0  # Dirichlet boundary condition p = 0 at y = 1

    p = p_new.copy()

# Plotting pressure p
fig = plt.figure()
ax = fig.gca(projection = '3d')
X,Y = np.meshgrid(x,y)
surf = ax.plot_surface(X, Y, p[:], cmap=cm.viridis)
plt.show()


import numpy as np

def minmax_norm(data):
    Mindata = np.tile(np.min(data,axis=0),(data.shape[0],1));
    Maxdata = np.tile(np.max(data,axis=0),(data.shape[0],1));
    return (data-Mindata)/(Maxdata-Mindata)


"""
This module implements rigid factorization.
"""

import numpy as np
from numpy.linalg import svd, solve
import numpy.linalg
import model
import util
from model import BasisShapeModel

def factor_matrix(W, J=3):
    """Obtain the best rank J factorization MS to W

    Computes a factorization of W into M and B such that ||W-MB||_F
    is minimized.

    Input:
    W is a MxN matrix.

    Returns:
    M -- A MxR matrix
    B -- A RxN matrix
    """

    # Decompose using SVD.
    U, s, Vt = svd(W, full_matrices=0)

    # Compute the factorization.
    sqrt_sigma = np.diag(np.sqrt(s[:J]))
    M = np.dot(U[:,:J], sqrt_sigma)
    B = np.dot(sqrt_sigma, Vt[:J])

    return M, B

def factor(W):
    """
    This implements rigid factorization as described in

    Tomasi, C. & Kanade, T. "Shape and motion from image streams under
    orthography: a factorization method International Journal of Computer
    Vision, 1992
    """

    F = W.shape[0]/2
    N = W.shape[1]

    # Center W
    T = W.mean(axis=1)
    W = W - T[:, np.newaxis]

    # Factor W
    M_hat, B_hat = factor_matrix(W, J=3)

    # Where we will build the linear system.
    A = np.zeros((3*F, 6))
    b = np.zeros((3*F,))

    for f in range(F):

        # Extract the two rows.
        x_f, y_f = M_hat[f*2:f*2+2]

        # Both rows must have unit length.
        A[f*3] = util.vc(x_f, x_f)
        b[f*3] = 1.0
        A[f*3+1] = util.vc(y_f,y_f)
        b[f*3+1] = 1.0

        # And be orthogonal.
        A[f*3+2] = util.vc(x_f - y_f, x_f + y_f)

    # Recovec vech(Q) and Q
    vech_Q = np.linalg.lstsq(A, b)[0]
    Q = util.from_vech(vech_Q, 3, 3, sym=True)

    # Factor out G recovery matrix
    G, Gt = factor_matrix(Q)

    # Upgrade M and B.
    M = np.dot(M_hat, G)
    B = np.linalg.solve(G, B_hat)

    # Find actual rotations matrices.
    Rs = np.zeros((F, 3, 3))
    Rs[:,:2] = M.reshape(F,2,3)
    Rs[:,2] = util.normed(np.cross(Rs[:,0], Rs[:,1], axis=-1))

    # And 3D translations.
    Ts = np.zeros((F,3))
    Ts[:,:2] = T.reshape(F,2)

    model = BasisShapeModel(Rs, Bs = B[np.newaxis,:,:], Ts = Ts)

    return model

def main():

    gt_model = model.rigid_model(100)

    W = gt_model.W

    inf_model = factor(W)
    inf_model.register(gt_model)

    model.compare(inf_model, gt_model)

if __name__ == '__main__':
    main()


from numpy import array
from NIM.benchmarks.benchmark import Benchmark

class Camel6(Benchmark):
    """dim: 2"""
    def __init__(self, lower=(-3, -2), upper=(3, 2), dimension=2):
        super(Camel6, self).__init__(lower, upper, dimension)

    def get_optimum(self):
        return array([[0.0898, -0.7126], [-0.0898, 0.7126]]), -1.0316284229280819

    @staticmethod
    def eval(sol):
        term1 = (4 - 2.1 * sol[0] ** 2 + (sol[0] ** 4) / 3) * sol[0] ** 2
        term2 = sol[0] * sol[1]
        term3 = (-4 + 4 * sol[1] ** 2) * sol[1] ** 2

        return term1 + term2 + term3


import numpy as np

"""
Convert linear frequency to wavenumber
"""
def f_to_k(f,c = 343):
    return 2*np.pi*f / c

"""
Convert wavenumber to linear frequency
"""
def k_to_f(k,c = 343):
    return k*c/(2*np.pi)


from math import cos, sin

import numpy as np

def gram_schmidt(vecs, thresh=1e-8):
    def proj(v1, v2): return v1.dot(v2)/v1.dot(v1)
    ortho = [vecs[0], ]
    for v1 in vecs[1:]:
        tmp = v1.copy()
        for v2 in ortho:
            tmp -= proj(v2, v1)*v2
        norm = np.linalg.norm(tmp)
        # Don't append linear dependent vectors, as their norm will be
        # near zero. Renormalizing them to unity would lead to numerical
        # garbage and to erronous results later on, when we orthgonalize
        # against this 'arbitrary' vector.
        if norm <= thresh:
            continue
        ortho.append(tmp / norm)
    return np.array(ortho)

def perp_comp(vec, along):
    """Return the perpendicular component of vec along along."""
    return vec - vec.dot(along)*along

def make_unit_vec(vec1, vec2):
    """Return unit vector pointing from vec2 to vec1."""
    diff = vec1 - vec2
    return diff / np.linalg.norm(diff)

def svd_inv(array, thresh, hermitian=False):
    U, S, Vt = np.linalg.svd(array, hermitian=hermitian)
    keep = S > thresh
    S_inv = np.zeros_like(S)
    S_inv[keep] = 1 / S[keep]
    return Vt.T.dot(np.diag(S_inv)).dot(U.T)

def get_rot_mat(abc=None):
    # Euler angles
    if abc is None:
        abc = np.random.rand(3)*np.pi*2
    a, b, c = abc
    R = np.array((
        (cos(a)*cos(b)*cos(c)-sin(a)*sin(c),
        -cos(a)*cos(b)*sin(c)-sin(a)*cos(c),
         cos(a)*sin(b)),
        (sin(a)*cos(b)*cos(c)+cos(a)*sin(c),
        -sin(a)*cos(b)*sin(c)+cos(a)*cos(c),
         sin(a)*sin(b)),
        (-sin(b)*cos(c),
          sin(b)*sin(c),
          cos(b)))
    )
    return R


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

"""
Use a logarithmic scale on both axis
"""

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

# Build datas ###############

#x = np.arange(0.1, 100, 1)  # bad
x = np.exp(np.arange(0, 3, 0.05) * math.log(10))

print(x)

yl1 = np.log(x)
yl2 = x * np.log(x)
y1 = x
y2 = np.power(x,2)
y3 = np.power(x,3)
ye = np.exp(x * math.log(2))

# Plot data #################

plt.plot(x, yl1, ".", x, yl2, ".", x, y1, ".", x, y2, ".", x, y3, ".", ye, "--")
plt.xscale('log')
plt.yscale('log')

plt.xlabel(r'$x$')
plt.ylabel(r'$f(y)$')

plt.legend(["log(x)", "x log(x)", "x", "x^2", "x^3", "2^x"])

plt.title('log scale')

plt.ylim(ymax = math.exp(20 * math.log(10)))

# Save file and plot ########

plt.savefig("log_scale.png")
plt.show()


"""
@author: roycek
"""

import numpy as np

def normalize_data(data_X):
    return (data_X - data_X.mean()) / data_X.std()

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

def theta_closed_form(data_X, y_label):
    return np.linalg.pinv(np.dot(data_X.T, data_X)) * np.dot(data_X.T, np.mat(y_label))

def mean_square_error(y_train, y_pred):
    return np.square(np.subtract(y_train, y_pred)).mean()

def insert_weight_one(train_x):
    weight_ones = np.ones((train_x.shape[0], 1))
    return np.hstack((train_x, weight_ones))

def load_dataset(file):
    dataset = np.loadtxt(file, usecols=range(0, 14))
    x = normalize_data(dataset[:, :-1])
    y = dataset[:, -1].reshape((-1, 1))
    return x, y

train_X, train_y = load_dataset("housing_train.txt")
X = insert_weight_one(train_X)
theta = theta_closed_form(X, train_y)
y_ = predict(X, theta)
mse = mean_square_error(train_y, y_)

test_X, test_y = load_dataset("housing_test.txt")
test_x = insert_weight_one(test_X)
t_y = predict(test_x, theta)
mse_test = mean_square_error(test_y, t_y)

print(f'theta: \n{theta}')
print(f'mse_training: {mse}, mse_test: {mse_test}')


#!/usr/bin/env python3

import sys

from numpy import sqrt, power, sin, cos, deg2rad

def rotate(x, y, angle):

    _x = x * cos(angle) - y * sin(angle)
    _y = x * sin(angle) + y * cos(angle)

    return _x, _y

def vector_length(x, y, z):
    return sqrt(power(x, 2) + power(y, 2) + power(z, 2))

def main(x, y, z, alpha, beta, gamma):

    # rotate in X axes
    y_rx, z_rx = rotate(y, z, alpha)

    # rotate in Y axes
    z_ry, x_ry = rotate(z_rx, x, beta)

    # rotate in Z axes
    x_rz, y_rz = rotate(x_ry, y_rx, gamma)

    print("x: {}".format(x_rz))
    print("y: {}".format(y_rz))
    print("z: {}".format(z_ry))

    print("lenght: {}".format(vector_length(x_rz, y_rz, z_ry)))

if __name__ == '__main__':

    if len(sys.argv) < 7:
        print("Usage: ./rotate.py x y z alpha beta gamma")
        print("alpha | beta | gamma are angles in degrees")
        sys.exit(0)

    x = float(sys.argv[1])
    y = float(sys.argv[2])
    z = float(sys.argv[3])
    alpha = deg2rad(float(sys.argv[4]))
    beta = deg2rad(float(sys.argv[5]))
    gamma = deg2rad(float(sys.argv[6]))

    main(x, y, z, alpha, beta, gamma)


## Standard Library Imports

## Library Imports
import numpy as np
from scipy import fft
from IPython.core import debugger
breakpoint = debugger.set_trace

## Local Imports
from .shared_constants import *

def dct2(x):
	return fft.dct(fft.dct(x, norm='ortho', axis=-2), norm='ortho', axis=-1)

def idct2(x):
	return fft.idct(fft.idct(x, norm='ortho', axis=-2), norm='ortho', axis=-1)

def generate_dct2d_mat(nr, nc):
	A = np.kron(
		fft.idct(np.identity(nr), norm='ortho', axis=1),
		fft.idct(np.identity(nc), norm='ortho', axis=1)
		)
	return A.reshape((nr*nc, nr, nc))


import os
import numpy as np
from scipy.io import loadmat
from ex3_utils import displayData, sigmoid

## Machine Learning Online Class - Exercise 3 | Part 2: Neural Networks

def predict(Theta1, Theta2, X):
    m = X.shape[0]
    X = np.c_[np.ones(m), X]
    A2 = np.c_[np.ones(m), sigmoid(X @ Theta1.T)]
    pred = np.argmax(sigmoid(A2 @ Theta2.T), axis=1) #A3
    return pred + 1

# =========== Part 1: Loading and Visualizing Data =============
#  We start the exercise by first loading and visualizing the dataset.
#  You will be working with a dataset that contains handwritten digits.

# Load Training Data
print('Loading and Visualizing Data ...')

scriptdir = os.path.dirname(os.path.realpath(__file__))
data = loadmat(scriptdir + '//ex3data1.mat') # training data stored in arrays X, y
X = data['X']
y = data['y'].ravel()
num_labels = 10          # 10 labels, from 1 to 10

m, input_layer_size = X.shape #400 = 20x20 Input Images of Digits
hidden_layer_size = 25   # 25 hidden units

# Randomly select 100 data points to display
sel = np.random.choice(m, 100, replace=False)
displayData(X[sel, :])

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

# ================ Part 2: Loading Pameters ================
# In this part of the exercise, we load some pre-initialized
# neural network parameters.

print('\nLoading Saved Neural Network Parameters ...')

# Load the weights into variables Theta1 and Theta2
weight = loadmat(scriptdir + '//ex3weights.mat')
Theta1 = weight['Theta1']
Theta2 = weight['Theta2']

# ================= Part 3: Implement Predict =================
#  After training the neural network, we would like to use it to predict
#  the labels. You will now implement the "predict" function to use the
#  neural network to predict the labels of the training set. This lets
#  you compute the training set accuracy.

pred = predict(Theta1, Theta2, X)

print(f'\nTraining Set Accuracy: {np.mean(pred == y) * 100}\n', )

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

#  To give you an idea of the network's output, you can also run
#  through the examples one at the a time to see what it is predicting.

#  Randomly permute examples

for i in np.random.permutation(m):
    # Display
    print('\nDisplaying Example Image')
    displayData(X[np.newaxis, i])

    pred = predict(Theta1, Theta2, X[np.newaxis, i])
    print(f'\nNeural Network Prediction: {pred[0]} (digit {np.mod(pred[0], 10)})\n')
    print(f'Actual y label : {np.mod(y[i], 10)}\n')
    # Pause with quit option
    s = input('Paused - press enter to continue, q to exit:')
    if s == 'q':
        break


# -*- coding: utf-8 -*-
# ----------------------------------------------------------------------------
# Created By  : Vítor Pereira
# Created Date: 01-09-2021
# version ='0.0.1'
# ---------------------------------------------------------------------------
"""Principal Component Analysis module"""
# ---------------------------------------------------------------------------
import numpy as np
from ..data import StandardScaler

class PCA:

    def __init__(self, n_components=2, svd=True, scale=True) -> None:
        self.n_components = n_components
        self.svd = svd
        self.scale = scale

    def fit(self, dataset):
        X = dataset.X
        if self.scale:
            X_scale = StandardScaler().fit_transform(dataset)
            self.X_center = X_scale.X
        else:
            # may use the center instead of std scaler
            self.X_center = X - np.mean(X, axis=0)

        if self.svd:
            # uses SVD
            self.e_vecs, self.e_vals, vt = np.linalg.svd(self.X_center.T)
        else:
            # uses GEEV right eigen vector on the covariance matrix
            cov_matrix = np.cov(self.X_center.T)
            self.e_vals, self.e_vecs = np.linalg.eig(cov_matrix)

    def transform(self, dataset):
        self.sorted_index = np.argsort(self.e_vals)[::-1]
        self.e_vals_sorted = self.e_vals[self.sorted_index]
        self.e_vecs_sorted = self.e_vecs[:, self.sorted_index]
        self.e_vecs_subset = self.e_vecs_sorted[:, 0:self.n_components]
        X_reduced = self.e_vecs_subset.T.dot(self.X_center.T).T
        return X_reduced

    def fit_transform(self, dataset):
        self.fit(dataset)
        return self.transform(dataset)

    def variance_explained(self):
        _sum = sum(self.e_vals_sorted)
        return [(i/_sum*100) for i in self.e_vals_sorted]


# Technique 2:  This can be used for fitting a gaussian when your data is not from a histogram but from a profile (i.e y axis is not counts but some parameter)
# We will use optimize module from scipy
# infact this technique can be used for fitting to any arbitary function

import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit

def gaus(x,a,mu,sd):
    return a*np.exp(-(x-mu)**2/(2*sd**2))

x = np.arange(-3,3,0.1)
y = gaus(x,10,0,1) # mean zero and sd 1, with amplitude 10

# popt is an array of parameters and pcov is the matrix of covarianes
popt,pcov = curve_fit(gaus,x,y,p0=[1,1,1]) # the number within square brackets are the initial values.

plt.plot(x,y,'b+:',label='data')
plt.plot(x,gaus(x,*popt),'ro:',label='fit')
plt.legend()
plt.show()

# assignment
# generate a data set containing numbers from an exponential decay function
# write a function to fit the dataset to an exponential decay and find the fit parameters


import numpy as np
from sklearn.svm import SVR
import matplotlib.pyplot as plt
from scipy.stats import multivariate_normal
from mpl_toolkits.mplot3d import Axes3D
from PIL import Image
from PIL import ImageOps

m = 2 #dimension
mean = np.zeros(m)
sigma = np.eye(m)

N = 100
x1 = np.linspace(-5, 5, N)
x2 = np.linspace(-5, 5, N)

X1, X2 = np.meshgrid(x1, x2)
X = np.c_[np.ravel(X1), np.ravel(X2)]

# アウトプットを算出
s=10
y = np.sin(X1).ravel()+ np.cos(X2).ravel()  #+1 * (0.5 - np.random.rand(X1))

for i in range(len(y)):
    #print(X1[i],y[i],np.random.rand())
    y[i] = y[i]  +s*(0.5 - np.random.rand())
#y_o = y.copy()

y1 = y.reshape(X1.shape)

#Y_plot = multivariate_normal.pdf(x=X, mean=mean, cov=sigma)
#Y_plot = Y_plot.reshape(X1.shape)
# ノイズを加える
#y1[::5] += 1 * (0.5 - np.random.rand(20,100))

fig=plt.figure(figsize=(12, 10))
ax1 = fig.add_subplot(211, projection='3d')
ax2 = fig.add_subplot(212, projection='3d')
surf = ax2.plot_surface(X1, X2, y1, cmap='bwr', linewidth=0) #Y_plot
fig.colorbar(surf)
ax1.scatter3D(np.ravel(X1), np.ravel(X2), y)
ax2.set_title("Surface Plot")
ax1.set_title("scatter Plot")
plt.savefig('Surface_plot2_input'+str(s)+'.jpg')
plt.pause(1)
plt.close()

# フィッティング
svr_rbf = SVR(kernel='rbf', C=1e3, gamma=0.1)
#svr_lin = SVR(kernel='linear', C=1e3)
#svr_poly = SVR(kernel='poly', C=1e3, degree=3)
y_rbf = svr_rbf.fit(X, y).predict(X)
#y_lin = svr_lin.fit(X, y).predict(X)
#y_poly = svr_poly.fit(X, y).predict(X)

# テストデータも準備
#test_X1 = np.sort(5 * np.random.rand(40, 1).reshape(40), axis=0)
#test_X2 = np.sort(3 * np.random.rand(40, 1).reshape(40), axis=0)

N = 100
test_x1 = np.linspace(-5, 5, N)
test_x2 = np.linspace(-5, 5, N)

test_X1, test_X2 = np.meshgrid(test_x1, test_x2)
test_X = np.c_[np.ravel(test_X1), np.ravel(test_X2)]

#test_X = np.c_[test_X1, test_X2]
#test_y = np.sin(test_X1).ravel() + np.cos(test_X2).ravel()

# テストデータを突っ込んで推定してみる
test_rbf = svr_rbf.predict(test_X)
#test_lin = svr_lin.predict(test_X)
#test_poly = svr_poly.predict(test_X)
test_rbf1 = test_rbf.reshape(test_X1.shape)

fig=plt.figure(figsize=(12, 10))
ax1 = fig.add_subplot(211, projection='3d')
ax2 = fig.add_subplot(212, projection='3d')
#ax3 = fig.add_subplot(313)
ax1.set_title('Graph')
ax1.scatter3D(np.ravel(test_X1), np.ravel(test_X2), test_rbf)
surf = ax2.plot_surface(test_X1, test_X2, test_rbf1, cmap='bwr', linewidth=0) #Y_plot
fig.colorbar(surf)
#ax1.scatter3D(np.ravel(test_X1), np.ravel(test_X2), test_lin)
#ax1.scatter3D(np.ravel(test_X1), np.ravel(test_X2), test_poly)
plt.savefig('Surface_svr_rbf_prediction'+str(s)+'.jpg')
plt.pause(1)
plt.close()

from sklearn.metrics import mean_squared_error
from math import sqrt

test_y = np.sin(test_X1).ravel() + np.cos(test_X2).ravel()
# 相関係数計算
rbf_corr = np.corrcoef(test_y, test_rbf)[0, 1]
rbf_corr1 = np.corrcoef(y, test_rbf)[0, 1]
#lin_corr = np.corrcoef(test_y, test_lin)[0, 1]
#poly_corr = np.corrcoef(test_y, test_poly)[0, 1]

# RMSEを計算
rbf_rmse = sqrt(mean_squared_error(test_y, test_rbf))
rbf_rmse1 = sqrt(mean_squared_error(y, test_rbf))
#lin_rmse = sqrt(mean_squared_error(test_y, test_lin))
#poly_rmse = sqrt(mean_squared_error(test_y, test_poly))

print( "RBF: RMSE %f \t\t Corr %f" % (rbf_rmse, rbf_corr))
print( "RBF: RMSE with original %f \t\t Corr %f" % (rbf_rmse1, rbf_corr1))
#print( "Linear: RMSE %f \t Corr %f" % (lin_rmse, lin_corr))
#print( "Poly: RMSE %f \t\t Corr %f" % (poly_rmse, poly_corr))


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Mon Feb  7 19:00:59 2022

@author: daneel
"""
import numpy as np

def gauss_seidel(A, b, tolerance=1e-10, max_iterations=100000, verbose=False):
    """
    Simple Function for the Gauss-Seidel Method for solving a system of linear
    equations
    Returns a numpy array consisting of the solution x, where A . x = b

            Parameters:
                    A (numpy array): A square matrix of coefficients
                    b (numpy array): The RHS vector of the linear system

            Returns:
                    x (numpy array): Solution to the equation A . x = b
    """
    x = np.zeros_like(b, dtype=np.double)

    if verbose:
        print("Iteration\t% soln: Relative err")
    # Iterate
    for k in range(max_iterations):
        x_old = x.copy()

        # Loop over rows
        for i in range(A.shape[0]):
            x[i] = (b[i] - np.dot(A[i, :i], x[:i]) -
                    np.dot(A[i, (i+1):], x_old[(i+1):])) / A[i, i]

        error = np.linalg.norm(x - x_old,
                               ord=np.inf) / np.linalg.norm(x, ord=np.inf)
        if verbose:
            print("%lf\t %1.4lf " % (k, error * 100))

        # Stop condition
        if error < tolerance:
            break
    if k == max_iterations - 1:
        raise StopIteration("Error: Maximum iterations exceeded", k)

    return x

def isDDM(m, n):
    """
    Checks a numpy 2d square array for diagonal dominance
    """

    # for each row
    for i in range(0, n):
        # for each column, finding sum of each row sans the diagonal
        sum = np.sum(m[i]) - np.abs(m[i, i])
        if (abs(m[i, i]) < sum):
            return False

    return True

if __name__ == '__main__':
    mat = np.array([[16, 3],
                    [7, -11]])

    rhs = np.array([11,
                    13])

    print("x =", gauss_seidel(mat, rhs, verbose=True))
    mat = np.array([[25, 5, 1],
                    [64, 8, 1],
                    [144, 12, 1]])

    rhs = np.array([106.8,
                    177.2,
                    279.2])

    print("Is matrix diagonally dominant?", isDDM(mat, 3))
    # NOTE: Uncomment the line below to induce an exception arising due to lack of diagonal dominance
    # print("x =", gauss_seidel(mat, rhs))

    mat = np.array([[12, 3, -5],
                    [1,  5,  3],
                    [3,  7, 13]])

    rhs = np.array([1,
                    28,
                    76])

    print("Is matrix diagonally dominant?", isDDM(mat, 3))
    print("x =", gauss_seidel(mat, rhs))
    mat = np.array([[1,  5,  3],
                    [12, 3, -5],
                    [3,  7, 13]])

    rhs = np.array([28,
                    1,
                    76])

    print("Is matrix diagonally dominant?", isDDM(mat, 3))

    try:
        print("x =", gauss_seidel(mat, rhs))
    except Exception:
        print("The algorithm failed to converge")


import math

import numpy as np
import pytest

from skspatial.objects import Sphere

@pytest.mark.parametrize(
    "point, radius",
    [
        # The point must be 3D.
        ([0], 1),
        ([0, 0], 1),
        ([0, 0, 0, 0], 1),
        ([1, 2, 3, 4], 1),
        # The radius must be positive.
        ([0, 0, 0], 0),
        ([0, 0, 0], -1),
        ([0, 0, 0], -5),
    ],
)
def test_failure(point, radius):

    with pytest.raises(Exception):
        Sphere(point, radius)

@pytest.mark.parametrize(
    "radius, surface_area_expected, volume_expected",
    [
        (1, 4 * np.pi, 4 / 3 * np.pi),
        (2, 16 * np.pi, 32 / 3 * np.pi),
        (3, 36 * np.pi, 36 * np.pi),
        (4.5, 81 * np.pi, 121.5 * np.pi),
        (10, 400 * np.pi, 4000 / 3 * np.pi),
    ],
)
def test_surface_area_volume(radius, surface_area_expected, volume_expected):

    sphere = Sphere([0, 0, 0], radius)

    assert math.isclose(sphere.surface_area(), surface_area_expected)
    assert math.isclose(sphere.volume(), volume_expected)


import numpy as np

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

def sigmoid_derivative(z):
    return sigmoid(z) * (1 - sigmoid(z))

def tanh(z):
    return np.tanh(z)

def tanh_derivative(z):
    return 1 - np.square(np.tanh(z))

def relu(z):
    return z * (z > 0)

def relu_derivative(z):
    return 1.0 * (z > 0)

def identify(z):
    return z

def identify_derivative(z):
    return 1

def softmax(z, axis):
    t = np.exp(z)
    return t / np.sum(t, axis=axis)


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

# In[1]:

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

def f1(x, y):
    return y - x ** 2 / 2 + x - 0.5

def f1_xprime(x, y):
    return -x + 1

def f1_yprime(x, y):
    return 1

def f2(x, y):
    return 2 * x + y - y ** 3 / 6 - 1.6

def f2_xprime(x, y):
    return 2

def f2_yprime(x, y):
    return -y ** 2 / 2 + 1

def f(x, y):
    return np.array([f1(x, y), f2(x, y)], dtype=np.double)

def df(x, y):
    return np.array([[f1_xprime(x, y), f1_yprime(x, y)], [f2_xprime(x, y), f2_yprime(x, y)]], dtype=np.double)

def ysub(x):
    return 0.5 * x ** 2 - x + 0.5

def ysub_prime(x):
    return x - 1

def f2_ysub(x):
    return f2(x, ysub(x))

def f2_ysub_prime(x):
    return 2 + ysub_prime(x) - (ysub(x) ** 2) * ysub_prime(x) / 2

def infNorm(x):
    return np.max(np.abs(x))

# In[2]:

import Newton

intervals = Newton.get_intervals_table(0.0, 5.0, f2_ysub, 100)

roots = np.array([(interval[0] + interval[1]) / 2 for interval in intervals])
radii = np.array([max((ysub(interval[1]) - ysub(interval[0])) / 2, interval[1] - interval[0]) for interval in intervals])

print("x values for starting points: " + str(roots))
print("Sphere radia: " + str(radii))

points = np.array([(root, ysub(root)) for root in roots], dtype=np.double)

print("Starting points: " + str(points))


import numpy as np
import pylab
import matplotlib.image as mpimg
import matplotlib.pyplot as plt
from scipy import ndimage
# signal.py: TODO: try to not make use of transform.resize
from skimage import transform
from . import general as nt # nt is the NumericalTour toolbox by Gabriel Peyre
#from nt_toolbox.general import *

from scipy.fftpack import dct
from scipy.fftpack import idct
from skimage.io import imread as skimread
from skimage.util.dtype import img_as_float

def imread(image_path):
    # Takes an image file (.png, .jpg etc) and returns a 2D np.array
    return img_as_float(skimread(image_path))

def imshow(image):
    # Takes an 2D np.array and displays it in shades of gray
    _ = plt.imshow(image, cmap="gray", interpolation="none")

def dct2(image):
    return dct(dct(image.T, norm='ortho').T, norm='ortho')

def idct2(coefficient):
    return idct(idct(coefficient.T, norm='ortho').T, norm='ortho')

def create_kernel(kernel_size, kernel_std):
    x = np.concatenate((np.arange(0, kernel_size / 2), np.arange(-kernel_size / 2, 0)))
    [Y, X] = np.meshgrid(x, x)
    kernel = np.exp((-X**2 - Y**2) / (2 * kernel_std**2))
    kernel = kernel / sum(kernel.flatten())
    return kernel

def gaussian_kernel(kernel_size, kernel_std, im_shape):
    kernel = create_kernel(kernel_size, kernel_std)
    padded_kernel = np.zeros(im_shape)
    padded_kernel[0:kernel.shape[0], 0:kernel.shape[1]] = kernel
    e = np.zeros(im_shape)
    e[0,0] = 1
    i = int(np.floor(kernel.shape[0]/2)+1)
    j = int(np.floor(kernel.shape[1]/2)+1)
    center = np.array([i, j])
    m = im_shape[0]
    n = im_shape[1]
    k = min(i-1,m-i,j-1,n-j)

    PP = padded_kernel[i-k-1:i+k, j-k-1:j+k]
    Z1 = np.diag(np.ones((k+1)),k)
    Z2 = np.diag(np.ones((k)),k+1)
    PP = Z1@PP@Z1.T + Z1@PP@Z2.T + Z2@PP@Z1.T + Z2@PP@Z2.T

    Ps = np.zeros(im_shape)
    Ps[0:2*k+1, 0:2*k+1] = PP
    kernel_fourier = dct2(Ps)/dct2(e)
    return kernel_fourier

def blur(x, kernel_fourier):
    return np.real(idct2(dct2(x) * kernel_fourier))

def bilinear_interpolate(im, x, y):
    x = np.asarray(x)
    y = np.asarray(y)

    x0 = np.floor(x).astype(int)
    x1 = x0 + 1
    y0 = np.floor(y).astype(int)
    y1 = y0 + 1

    x0 = np.clip(x0, 0, im.shape[1]-1);
    x1 = np.clip(x1, 0, im.shape[1]-1);
    y0 = np.clip(y0, 0, im.shape[0]-1);
    y1 = np.clip(y1, 0, im.shape[0]-1);

    Ia = im[ y0, x0 ]
    Ib = im[ y1, x0 ]
    Ic = im[ y0, x1 ]
    Id = im[ y1, x1 ]

    wa = (x1-x) * (y1-y)
    wb = (x1-x) * (y-y0)
    wc = (x-x0) * (y1-y)
    wd = (x-x0) * (y-y0)

    return wa*Ia + wb*Ib + wc*Ic + wd*Id

def cconv(x, h, d):
    """
        Circular convolution along dimension d.
        h should be small and with odd size
    """
    if d == 2:
        # apply to transposed matrix
        return np.transpose(cconv(np.transpose(x), h, 1))
    y = np.zeros(x.shape)
    p = len(h)
    pc = int(round( float((p - 1) / 2 )))
    for i in range(0, p):
        y = y + h[i] * nt.circshift1d(x, i - pc)
    return y

def div(g):
    """
        Compute a finite difference approximation of the gradient of a 2D vector field, assuming periodic BC.
    """
    S = g.shape;
    s0 = np.concatenate( ([S[0]-1], np.arange(0,S[0]-1)) )
    s1 = np.concatenate( ([S[1]-1], np.arange(0,S[1]-1)) )
    f = (g[:,:,0] - g[s0,:,0]) + (g[:,:,1]-g[:,s1,1])
    return f

def gaussian_blur(f, sigma):

    """ gaussian_blur - gaussian blurs an image
    %
    %   M = perform_blurring(M, sigma, options);
    %
    %   M is the original data
    %   sigma is the std of the Gaussian blur (in pixels)
    %
    %   Copyright (c) 2007 Gabriel Peyre
    """
    if sigma<=0:
        return;
    n = max(f.shape);
    t = np.concatenate( (np.arange(0,n/2+1), np.arange(-n/2,-1)) )
    [Y,X] = np.meshgrid(t,t)
    h = np.exp( -(X**2+Y**2)/(2.0*float(sigma)**2) )
    h = h/np.sum(h)
    return np.real( pylab.ifft2(pylab.fft2(f) * pylab.fft2(h)) )

def grad(f):
    """
        Compute a finite difference approximation of the gradient of a 2D image, assuming periodic BC.
    """
    S = f.shape;
#   g = np.zeros([n[0], n[1], 2]);
    s0 = np.concatenate( (np.arange(1,S[0]),[0]) )
    s1 = np.concatenate( (np.arange(1,S[1]),[0]) )
    g = np.dstack( (f[s0,:] - f, f[:,s1] - f))
    return g

def imageplot(f, str='', sbpt=[]):
    """
        Use nearest neighbor interpolation for the display.
    """
    if sbpt != []:
        plt.subplot(sbpt[0], sbpt[1], sbpt[2])
    imgplot = plt.imshow(f, interpolation='nearest')
    imgplot.set_cmap('gray')
    pylab.axis('off')
    if str != '':
        plt.title(str)

def load_image(name, n=-1, flatten=1, resc=1, grayscale=1):
    """
        Load an image from a file, rescale its dynamic to [0,1], turn it into a grayscale image
        and resize it to size n x n.
    """
    f = plt.imread(name)
    # turn into normalized grayscale image
    if grayscale == 1:
        if (flatten==1) and np.ndim(f)>2:
            f = np.sum(f, axis=2)
    if resc==1:
        f = nt.rescale(f)
    # change the size of the image
    if n > 0:
        if np.ndim(f)==2:
            f = transform.resize(f, [n, n], 1)
        elif np.ndim(f)==3:
            f = transform.resize(f, [n, n, f.shape[2]], 1)
    return f

def perform_wavortho_transf(f, Jmin, dir, h):
    """
        perform_wavortho_transf - compute orthogonal wavelet transform

        fw = perform_wavortho_transf(f,Jmin,dir,options);

        You can give the filter in options.h.

        Works in 2D only.

        Copyright (c) 2014 Gabriel Peyre
    """

    n = f.shape[1]
    Jmax = int(np.log2(n)) - 1
    # compute g filter
    u = np.power(-np.ones(len(h) - 1), range(1, len(h)))
    # alternate +1/-1
    g = np.concatenate(([0], h[-1:0:-1] * u))

    if dir == 1:
        ### FORWARD ###
        fW = f.copy()
        for j in np.arange(Jmax, Jmin - 1, -1):
            A = fW[:2 ** (j + 1):, :2 ** (j + 1):]
            for d in np.arange(1, 3):
                Coarse = subsampling(cconv(A, h, d), d)
                Detail = subsampling(cconv(A, g, d), d)
                A = np.concatenate((Coarse, Detail), axis=d - 1)
            fW[:2 ** (j + 1):, :2 ** (j + 1):] = A
        return fW
    else:
        ### BACKWARD ###
        fW = f.copy()
        f1 = fW.copy()
        for j in np.arange(Jmin, Jmax + 1):
            A = f1[:2 ** (j + 1):, :2 ** (j + 1):]
            for d in np.arange(1, 3):
                if d == 1:
                    Coarse = A[:2**j:, :]
                    Detail = A[2**j: 2**(j + 1):, :]
                else:
                    Coarse = A[:, :2 ** j:]
                    Detail = A[:, 2 ** j:2 ** (j + 1):]
                Coarse = cconv(upsampling(Coarse, d), nt.reverse(h), d)
                Detail = cconv(upsampling(Detail, d), nt.reverse(g), d)
                A = Coarse + Detail
            f1[:2 ** (j + 1):, :2 ** (j + 1):] = A
        return f1

def plot_wavelet(fW, Jmin=0):
    """
        plot_wavelet - plot wavelets coefficients.

        U = plot_wavelet(fW, Jmin):

        Copyright (c) 2014 Gabriel Peyre
    """
    def rescaleWav(A):
        v = abs(A).max()
        B = A.copy()
        if v > 0:
            B = .5 + .5 * A / v
        return B
    ##
    n = fW.shape[1]
    Jmax = int(np.log2(n)) - 1
    U = fW.copy()
    for j in np.arange(Jmax, Jmin - 1, -1):
        U[:2 ** j:,    2 ** j:2 **
            (j + 1):] = rescaleWav(U[:2 ** j:, 2 ** j:2 ** (j + 1):])
        U[2 ** j:2 ** (j + 1):, :2 **
          j:] = rescaleWav(U[2 ** j:2 ** (j + 1):, :2 ** j:])
        U[2 ** j:2 ** (j + 1):, 2 ** j:2 ** (j + 1):] = (
            rescaleWav(U[2 ** j:2 ** (j + 1):, 2 ** j:2 ** (j + 1):]))
    # coarse scale
    U[:2 ** j:, :2 ** j:] = nt.rescale(U[:2 ** j:, :2 ** j:])
    # plot underlying image
    imageplot(U)
    # display crosses
    for j in np.arange(Jmax, Jmin - 1, -1):
        plt.plot([0, 2 ** (j + 1)], [2 ** j, 2 ** j], 'r')
        plt.plot([2 ** j, 2 ** j], [0, 2 ** (j + 1)], 'r')
    # display box
    plt.plot([0, n], [0, 0], 'r')
    plt.plot([0, n], [n, n], 'r')
    plt.plot([0, 0], [0, n], 'r')
    plt.plot([n, n], [0, n], 'r')
    return U

def psnr(x, y, vmax=-1):
    """
     psnr - compute the Peack Signal to Noise Ratio

       p = psnr(x,y,vmax);

       defined by :
           p = 10*log10( vmax^2 / |x-y|^2 )
       |x-y|^2 = mean( (x(:)-y(:)).^2 )
       if vmax is ommited, then
           vmax = max(max(x(:)),max(y(:)))

       Copyright (c) 2014 Gabriel Peyre
    """

    if vmax < 0:
        m1 = abs(x).max()
        m2 = abs(y).max()
        vmax = max(m1, m2)
    d = np.mean((x - y) ** 2)
    return 10 * np.log10(vmax ** 2 / d)

def snr(x, y):
    """
    snr - signal to noise ratio

       v = snr(x,y);

     v = 20*log10( norm(x(:)) / norm(x(:)-y(:)) )

       x is the original clean signal (reference).
       y is the denoised signal.

    Copyright (c) 2014 Gabriel Peyre
    """

    return 20 * np.log10(pylab.norm(x) / pylab.norm(x - y))

def subsampling(x, d):
    # subsampling along dimension d by factor p=2
    p = 2
    if d == 1:
        y = x[::p, :]
    elif d == 2:
        y = x[:, ::p]
    else:
        raise Exception('Not implemented')
    return y

def upsampling(x, d):
    """
        up-sampling along dimension d by factor p=2
    """
    p = 2
    s = x.shape
    if d == 1:
        y = np.zeros((p * s[0], s[1]))
        y[::p, :] = x
    elif d == 2:
        y = np.zeros((s[0], p * s[1]))
        y[:, ::p] = x
    else:
        raise Exception('Not implemented')
    return y

def plot_dictionary(D, title='Dictionary'):
    ''' Plot a dictionary of shape (width*width, n_atoms) '''
    # Check that D.shape == (width*width, n_atoms)
    assert len(D.shape) == 2
    assert int(np.sqrt(D.shape[0]))**2 == D.shape[0]
    (signal_size, n_atoms) = D.shape
    # Rescale values in each atom to have a max absolute value of 1
    # This gives brighter plots
    D = D / np.max(abs(D), axis=0)

    # Reshape dictionary to patches
    width = int(np.sqrt(D.shape[0]))
    D = D.reshape((width, width, n_atoms))
    n = int(np.ceil(np.sqrt(n_atoms)))  # Size of the plot in number of atoms

    # Pad the atoms
    pad_size = 1
    missing_atoms = n ** 2 - n_atoms

    padding = (((pad_size, pad_size), (pad_size, pad_size),
                (0, missing_atoms)))
    D = np.pad(D, padding, mode='constant', constant_values=1)
    padded_width = width + 2*pad_size
    D = D.reshape(padded_width, padded_width, n, n)
    D = D.transpose(2, 0, 3, 1)  # Needed for the reshape
    big_image_size = n*padded_width
    D = D.reshape(big_image_size, big_image_size)
    imageplot(D)
    plt.title(title)
    plt.show()


# -*- coding: utf-8 -*-
import sympy as sp

x = sp.symbols('x')

assert sp.pi == sp.integrate(sp.sqrt(1 - x**2), (x, -1, 1)) * 2
assert 1 == sp.integrate(sp.sin(x), (x, 0, sp.pi / 2))
assert 1 == sp.integrate(sp.cos(x), (x, 0, sp.pi / 2))
assert 1 == sp.integrate(sp.exp(x), (x, -sp.oo, 0))
assert sp.oo == sp.integrate(1.0 / x, (x, 0, 1))


import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_iris
from sklearn.model_selection import StratifiedKFold
from sklearn.metrics import accuracy_score , confusion_matrix

iris = load_iris()
X = iris.data
y = iris.target

X
y

skf = StratifiedKFold(n_splits = 5)

predict = np.zeros(y.shape[0])

for train,test in skf.split(X,y):
    x_train = X[train]
    x_test = X[test]
    y_train = y[train]
    y_test = y[test]
    logreg = LogisticRegression()
    logreg.fit(x_train , y_train)
    result= logreg.predict(x_test)
    predict[test] = result
    print('train data \n' , train)
    print('test data \n ', test)
    print('result \n',result)
    print('this accuracy \n' , accuracy_score(y_test , result))
    print('===============================')
    print()

print('total accuracy \n',accuracy_score(y , predict))

conf = confusion_matrix(y , predict)

print('confusion matrix \n',  conf)

Model Building/2.2 Logistic Regression/2.2.1.5.py


# Program 14c: Lyapunov exponents of the logistic map.
# See Figure 14.18.

import numpy as np
import matplotlib.pyplot as plt

num_points = 16000
result = []
lambdas = []
maps = []
xmin, xmax = 3, 4
mult = (xmax - xmin) * num_points

mu_values = np.arange(xmin, xmax, 20/num_points)

for r in mu_values:
    x = 0.1
    result = []
    for t in range(100):
        x = r * x * (1 - x)
        result.append(np.log(abs(r - 2*r*x)))
    lambdas.append(np.mean(result))
    # Ignore first 100 iterates.
    for t in range(20):
        x = r * x * (1 - x)
        maps.append(x)

fig = plt.figure(figsize=(10,7))
ax1 = fig.add_subplot(1,1,1)

xticks = np.linspace(xmin, xmax, mult)
zero = [0] * mult
ax1.plot(xticks, zero, 'k-', linewidth=3)
ax1.plot(xticks, maps,'r.', alpha = 0.3, label='Logistic map')
ax1.set_xlabel('r')
ax1.plot(mu_values, lambdas, 'b-', linewidth=1, label='Lyapunov exponent')
ax1.grid('on')
ax1.set_ylim(-1, 1)
ax1.set_xlabel('$\mu$', fontsize=15)
ax1.legend(loc='best')
ax1.set_title('Logistic map versus Lyapunov exponent', fontsize=15)

plt.show()


from .core import Tensor, exp, mean, sum, sin, cos, tan, log, rn_state
from .model import Module
import numpy as np

# Mean-Square Error
def mse_loss(x: Tensor, y: Tensor) -> Tensor:
    return mean((x - y) ** 2)

# Logistic Function (the exp(-x) is used to prevent floating-point overflow)
def sigmoid(x: Tensor) -> Tensor:
    return 1 / (1 + exp(-x))

# Softmax Function
def softmax(x: Tensor, axis=-1) -> Tensor:
    x = exp(x - np.nanmax(x.data, axis=axis, keepdims=True))
    return x / sum(x, axis=axis, keepdim=True)

# SiLU (also known as the Swish function, it is an activation function first introduced in `Gaussian Error Linear Units (GELUs)`)
def silu(x: Tensor) -> Tensor:
    return sigmoid(x) * x

# The one_hot encoding to convert our integer labels to vectors i.e. 7 -> [0, 0, 0, 0, 0, 0, 0, 1, 0, 0]
def one_hot(x: Tensor, num_classes: int) -> Tensor:
    return Tensor(np.eye(num_classes)[x.data.astype(int)])

# A module wrapper for the silu function
class SiLU(Module):
    def __init__(self):
        super().__init__()

    def forward(self, x: Tensor) -> Tensor:
        return silu(x)

# A module wrapper for the softmax function
class Softmax(Module):
    def __init__(self, axis=-1):
        super().__init__()
        self.axis = axis

    def forward(self, x: Tensor) -> Tensor:
        return softmax(x, axis=self.axis)

# A module wrapper for the sigmoid function
class Sigmoid(Module):
    def __init__(self):
        super().__init__()

    def forward(self, x: Tensor) -> Tensor:
        return sigmoid(x)


import numpy
import math
from scipy.optimize import root
from math import *

print('')
print('LIQUIDS PIPE SIZING CALCULATIONS')
print('')
print('INPUT DATA')
print('')
q = float(input('Please introduce liquid flow rate (US gpm): '))
ro = float(input('Please introduce liquid density (lb/ft3): '))
vi = float(input('Please introduce liquid viscosity (cP): '))
di = float(input('Please introduce pipe inner diameter (inches): '))
ru = float(input('Please introduce pipe roughness (inches): '))

def run ():
    print('')
    print('RESULTS')
    print('')
    flow_area = area (di)
    print("Pipe flow area is " + str(round(flow_area,4)) + " ft2")
    flow_velocity = velocity (q)
    print("Flow velocity is " + str(round(flow_velocity,2)) + " ft/s")
    reynolds_number = Reynolds (ro, vi)
    print("Reynolds number is " + str(round(reynolds_number,0)))
    relative_roughness = rr (ru, di)
    print("Relative roughness is " + str(round(relative_roughness,6)))
    factor = fac ()
    print("Darcy friction factor is " + str(round(factor,5)))
    droop_pressure = dp (ro,di)
    print('Droop pressure is ' + str(round(droop_pressure,5)) + ' psi/100ft')

def area (di):
    flow_area = 0.25*math.pi*((di/12)**2)
    return flow_area

def velocity (q):
    flow_area = area(di)
    flow_velocity = (0.00222801*q)/flow_area
    return flow_velocity

def Reynolds (ro, vi):
    flow_velocity = velocity (q)
    visc = vi * 0.000671969
    reynolds_number = ro * flow_velocity * (di/12) / visc
    return reynolds_number

def rr (ru, di):
    relative_roughness = ru/di
    return relative_roughness

def fac():
    reynolds_number = Reynolds (ro, vi)
    relative_roughness = rr (ru, di)
    if reynolds_number < 4000:
        friction_factor = 64/reynolds_number
        return friction_factor
    else:
        f2 = 0.01
        for i in range (1,6):
            f1 = 1/(-2*log((relative_roughness/3.7) + (2.51/(reynolds_number*sqrt(f2))),10))**2
            f2=f1
            i=i+1
        return f1

def dp (ro, di):
    flow_velocity = velocity (q)
    friction_factor = fac()
    gc = 32.17
    droop_pressure = (25/6)*friction_factor*ro*(flow_velocity**2)/(gc*di)
    return droop_pressure

if __name__ == "__main__":
    run ()


import numpy as np
import matplotlib.pyplot as plt

def lz(x, y, z, s=10, r=28, b=8./3.) :
    x_dot = s*(y - x)
    y_dot = r*x - y - x*z
    z_dot = x*y - b*z
    return x_dot, y_dot, z_dot

dt = 0.01
stepCnt = 300

tt = np.linspace(1,stepCnt,stepCnt)

n = 30

# Need one more for the initial values
xs = np.empty((stepCnt + 1,n))
ys = np.empty((stepCnt + 1,n))
zs = np.empty((stepCnt + 1,n))

# Setting initial values
for i in range(n):
    e = np.random.randn(3) * 1e-1
    #Ini3
    xs[0,i], ys[0,i], zs[0,i] = (10.+e[0] , 8.53+e[1], 28.+e[2])
    if i > 15:
        xs[0,i], ys[0,i], zs[0,i] = (-10.+e[0] , 2+e[1], 28.+e[2])
    else:
        xs[0,i], ys[0,i], zs[0,i] = (10.+e[0] , 8.53+e[1], 28.+e[2])

# Stepping through "time".
for i in range(stepCnt) :
    # Derivatives of the X, Y, Z state

    #euler forward
    dxyz = np.empty((3,n))

    for ii in range(n):
        dxyz[0,ii], dxyz[1,ii], dxyz[2,ii] = lz(xs[i,ii], ys[i,ii], zs[i,ii])

    xs[i+1,:] = xs[i,:] + (dxyz[0,:] * dt)
    ys[i+1,:] = ys[i,:] + (dxyz[1,:] * dt)
    zs[i+1,:] = zs[i,:] + (dxyz[2,:] * dt)

#plotting
fig, ax = plt.subplots()

line = []
poi = []

for t in range(stepCnt):
    if t == 0:
        for ii in range(n):
            ax.plot(xs[:,ii],zs[:,ii],'grey',lw=0.2)
            line1,poi1 = ax.plot(xs[0,ii],zs[0,ii],'b',xs[0,ii],zs[0,ii],'r.',lw=0.4,ms=10)
            line.append(line1)
            poi.append(poi1)

        ax.set_xlim(-30, 30)
        ax.set_ylim(0, 55)
        ax.set_xlabel('x')
        ax.set_ylabel('z')

    else:
        ii = 0
        for l in line:
            l.set_data(xs[:t,ii], zs[:t,ii])
            ii = ii+1

        ii = 0
        for p in poi:
            p.set_data(xs[t,ii], zs[t,ii])
            ii = ii+1

        ax.set_title('t='+str(t)+' / '+str(stepCnt))

    plt.pause(0.0001)

plt.pause(10)
plt.close('all')


import numpy as np
import xarray as xr
from scipy.stats import moment, skew, kurtosis

__all__ = ['sample_mean', 'sample_skewness', 'sample_kurtosis', 'xr_moment']

def xr_moment(x, dim, order=1):
    """Calculate statistical moment of an XArray DataArray object.

    Parameters
    ----------
    x : xarray object
    dim : str
        Dimension over which to calculate moment.
        Note: Only support calculation over a single dimension.
    order : int or array_like of ints, optional
        Order of central moment that is returned. Default is 1 (mean).

    Returns
    -------
    moment : Calculated moment as an XArray object.

    """
    return xr.apply_ufunc(
        moment, x, input_core_dims=[[dim]],
        kwargs={'moment': order, 'axis': -1, 'nan_policy': 'omit'},
        dask='parallelized', output_dtypes=[float]
    )

def sample_mean(data, error=True):
    dmean = np.mean(data)
    if error:
        mean_err = np.std(data, ddof=1) / np.sqrt(np.size(data))
        result = (dmean, mean_err)
    else:
        result = dmean
    return result

def sample_skewness(data, axis=None, bias=True, error=False):
    """
    Calculate sample skewness of data.

    Parameters
    ----------
    data : array-like
        Data array.
    axis : int or None, optional
        axis of the data array to computer skewness.
        Compute from the whole array if None.
    bias : bool, optional
        Computer biased of unbiased skewness. Default is True (biased).
    error : bool, optional
        Return standard error of the skewness if True. Default is False.
        Note that standard error is derived from the unbiased skewness.

    Returns
    -------
    skewness and standard error of skewness (if any)

    """
    dskew = skew(data, axis=axis, bias=bias)
    if error:
        nval = np.size(data)
        err = np.sqrt((6. * nval * (nval - 1)) /
                      ((nval - 2) * (nval + 1) * (nval + 3)))
        out = (dskew, err)
    else:
        out = dskew
    return out

def sample_kurtosis(data, axis=None, bias=True, error=False):
    """
    Calculate sample kurtosis of data.

    Parameters
    ----------
    data : array-like
        Data array.
    axis : int or None, optional
        axis of the data array to computer skewness.
        Compute from the whole array if None.
    bias : bool, optional
        Computer biased of unbiased skewness. Default is True (biased).
    error : bool, optional
        Return standard error of the skewness if True. Default is False.
        Note that standard error is derived from the unbiased skewness.

    Returns
    -------
    kurtosis and standard error of kurtosis (if any)

    """
    dkurt = kurtosis(data, axis=axis, bias=bias)
    if error:
        nval = np.size(data)
        err = np.sqrt((24. * nval * (nval - 1) ** 2) /
                      ((nval - 3) * (nval - 2) * (nval + 3) * (nval + 5)))
        out = (dkurt, err)
    else:
        out = dkurt
    return out


import numpy as np

def affine_forward(x, w, b):
  """
  Computes the forward pass for an affine (fully-connected) layer.

  The input x has shape (N, d_1, ..., d_k) and contains a minibatch of N
  examples, where each example x[i] has shape (d_1, ..., d_k). We will
  reshape each input into a vector of dimension D = d_1 * ... * d_k, and
  then transform it to an output vector of dimension M.

  Inputs:
  - x: A numpy array containing input data, of shape (N, d_1, ..., d_k)
  - w: A numpy array of weights, of shape (D, M)
  - b: A numpy array of biases, of shape (M,)

  Returns a tuple of:
  - out: output, of shape (N, M)
  - cache: (x, w, b)
  """
  out = None
  #############################################################################
  # TODO: Implement the affine forward pass. Store the result in out. You     #
  # will need to reshape the input into rows.                                 #
  #############################################################################
  N = x.shape[0]
  x_unravelled = x.reshape(N,-1)
  out = x_unravelled.dot(w)+b
  #############################################################################
  #                             END OF YOUR CODE                              #
  #############################################################################
  cache = (x, w, b)
  return out, cache

def affine_backward(dout, cache):
  """
  Computes the backward pass for an affine layer.

  Inputs:
  - dout: Upstream derivative, of shape (N, M)
  - cache: Tuple of:
    - x: Input data, of shape (N, d_1, ... d_k)
    - w: Weights, of shape (D, M)

  Returns a tuple of:
  - dx: Gradient with respect to x, of shape (N, d1, ..., d_k)
  - dw: Gradient with respect to w, of shape (D, M)
  - db: Gradient with respect to b, of shape (M,)
  """
  x, w, b = cache
  dx, dw, db = None, None, None
  #############################################################################
  # TODO: Implement the affine backward pass.                                 #
  #############################################################################
  N = x.shape[0]
  x_unravelled = x.reshape(N,-1)
  db = np.sum(dout,axis = 0)
  dw = x_unravelled.T.dot(dout)
  dx = dout.dot(w.T).reshape(x.shape)
  #############################################################################
  #                             END OF YOUR CODE                              #
  #############################################################################
  return dx, dw, db

def relu_forward(x):
  """
  Computes the forward pass for a layer of rectified linear units (ReLUs).

  Input:
  - x: Inputs, of any shape

  Returns a tuple of:
  - out: Output, of the same shape as x
  - cache: x
  """
  out = None
  #############################################################################
  # TODO: Implement the ReLU forward pass.                                    #
  #############################################################################
  f = lambda x:np.maximum(0,x)
  out = f(x)
  #############################################################################
  #                             END OF YOUR CODE                              #
  #############################################################################
  cache = x
  return out, cache

def relu_backward(dout, cache):
  """
  Computes the backward pass for a layer of rectified linear units (ReLUs).

  Input:
  - dout: Upstream derivatives, of any shape
  - cache: Input x, of same shape as dout

  Returns:
  - dx: Gradient with respect to x
  """
  dx, x = None, cache
  #############################################################################
  # TODO: Implement the ReLU backward pass.                                   #
  #############################################################################
  dx = np.copy(dout)
  dx[x < 0] = 0
  #############################################################################
  #                             END OF YOUR CODE                              #
  #############################################################################
  return dx

def batchnorm_forward(x, gamma, beta, bn_param):
  """
  Forward pass for batch normalization.

  During training the sample mean and (uncorrected) sample variance are
  computed from minibatch statistics and used to normalize the incoming data.
  During training we also keep an exponentially decaying running mean of the mean
  and variance of each feature, and these averages are used to normalize data
  at test-time.

  At each timestep we update the running averages for mean and variance using
  an exponential decay based on the momentum parameter:

  running_mean = momentum * running_mean + (1 - momentum) * sample_mean
  running_var = momentum * running_var + (1 - momentum) * sample_var

  Note that the batch normalization paper suggests a different test-time
  behavior: they compute sample mean and variance for each feature using a
  large number of training images rather than using a running average. For
  this implementation we have chosen to use running averages instead since
  they do not require an additional estimation step; the torch7 implementation
  of batch normalization also uses running averages.

  Input:
  - x: Data of shape (N, D)
  - gamma: Scale parameter of shape (D,)
  - beta: Shift paremeter of shape (D,)
  - bn_param: Dictionary with the following keys:
    - mode: 'train' or 'test'; required
    - eps: Constant for numeric stability
    - momentum: Constant for running mean / variance.
    - running_mean: Array of shape (D,) giving running mean of features
    - running_var Array of shape (D,) giving running variance of features

  Returns a tuple of:
  - out: of shape (N, D)
  - cache: A tuple of values needed in the backward pass
  """
  mode = bn_param['mode']
  eps = bn_param.get('eps', 1e-5)
  momentum = bn_param.get('momentum', 0.9)

  N, D = x.shape
  running_mean = bn_param.get('running_mean', np.zeros(D, dtype=x.dtype))
  running_var = bn_param.get('running_var', np.zeros(D, dtype=x.dtype))

  out, cache = None, None
  if mode == 'train':
    #############################################################################
    # TODO: Implement the training-time forward pass for batch normalization.   #
    # Use minibatch statistics to compute the mean and variance, use these      #
    # statistics to normalize the incoming data, and scale and shift the        #
    # normalized data using gamma and beta.                                     #
    #                                                                           #
    # You should store the output in the variable out. Any intermediates that   #
    # you need for the backward pass should be stored in the cache variable.    #
    #                                                                           #
    # You should also use your computed sample mean and variance together with  #
    # the momentum variable to update the running mean and running variance,    #
    # storing your result in the running_mean and running_var variables.        #
    #############################################################################
    x_mean = np.mean(x,axis = 0)
    x_variance = np.var(x,axis = 0)
    x_normed = (x-x_mean)/np.sqrt(x_variance+eps)
    out = gamma*x_normed+beta
    running_mean = momentum*running_mean+(1-momentum)*x_mean
    running_var = momentum*running_var+(1-momentum)*x_variance
    cache = (x,x_mean,x_variance,x_normed,gamma,beta,eps)
    #############################################################################
    #                             END OF YOUR CODE                              #
    #############################################################################
  elif mode == 'test':
    #############################################################################
    # TODO: Implement the test-time forward pass for batch normalization. Use   #
    # the running mean and variance to normalize the incoming data, then scale  #
    # and shift the normalized data using gamma and beta. Store the result in   #
    # the out variable.                                                         #
    #############################################################################
    x_normed = (x-running_mean)/np.sqrt(running_var+eps)
    out = gamma*x_normed+beta
    #############################################################################
    #                             END OF YOUR CODE                              #
    #############################################################################
  else:
    raise ValueError('Invalid forward batchnorm mode "%s"' % mode)

  # Store the updated running means back into bn_param
  bn_param['running_mean'] = running_mean
  bn_param['running_var'] = running_var

  return out, cache

def batchnorm_backward(dout, cache):
  """
  Backward pass for batch normalization.

  For this implementation, you should write out a computation graph for
  batch normalization on paper and propagate gradients backward through
  intermediate nodes.

  Inputs:
  - dout: Upstream derivatives, of shape (N, D)
  - cache: Variable of intermediates from batchnorm_forward.

  Returns a tuple of:
  - dx: Gradient with respect to inputs x, of shape (N, D)
  - dgamma: Gradient with respect to scale parameter gamma, of shape (D,)
  - dbeta: Gradient with respect to shift parameter beta, of shape (D,)
  """
  dx, dgamma, dbeta = None, None, None
  #############################################################################
  # TODO: Implement the backward pass for batch normalization. Store the      #
  # results in the dx, dgamma, and dbeta variables.                           #
  #############################################################################
  (x,x_mean,x_variance,x_normed,gamma,beta,eps) = cache
  N, D = x.shape

  # Backward for gamma scaling and beta shifting
  dbeta = np.sum(dout,axis = 0)
  dgamma = np.sum(dout*x_normed,axis = 0)
  dx_normed = dout*gamma

  # Backward for dividing standard deviation of x
  dinverse_x_sqrt_variance = np.sum(dx_normed*(x-x_mean),axis = 0)
  dx_minus_mean_1 = dx_normed*(1/(np.sqrt(x_variance+eps))) # The first route to x minus mean

  # Backward for inversing standard deviation of x
  dsqrt_of_mean_of_x_difference_square = dinverse_x_sqrt_variance*(-1/(x_variance+eps))

  # Backward for taking square root of variance of x
  dmean_of_x_difference_square = dsqrt_of_mean_of_x_difference_square*(0.5*(1/np.sqrt(x_variance+eps)))

  # Backward for the mean operation of (x-x_mean)^2
  dx_difference_square = (1/N)*np.ones((N,D))*dmean_of_x_difference_square

  # Backward for the square operation of (x-x_mean)
  dx_minus_mean_2 = 2*(x-x_mean)*dx_difference_square # The second route to x minus mean

  # Backward for (x-x_mean)
  dx_minus_mean = dx_minus_mean_1+dx_minus_mean_2

  # Backward for the minus operation of x and x_mean
  dminus_operation_x_and_mean = (-1)*np.sum(dx_minus_mean,axis = 0)
  dx1 = 1*(dx_minus_mean) # The first route to x

  # Backward for taking x mean
  dx2 = (1/N)*np.ones((N,D))*dminus_operation_x_and_mean # The second route to x

  # Finally
  dx = dx1+dx2
  #############################################################################
  #                             END OF YOUR CODE                              #
  #############################################################################

  return dx, dgamma, dbeta

def batchnorm_backward_alt(dout, cache):
  """
  Alternative backward pass for batch normalization.

  For this implementation you should work out the derivatives for the batch
  normalizaton backward pass on paper and simplify as much as possible. You
  should be able to derive a simple expression for the backward pass.

  Note: This implementation should expect to receive the same cache variable
  as batchnorm_backward, but might not use all of the values in the cache.

  Inputs / outputs: Same as batchnorm_backward
  """
  dx, dgamma, dbeta = None, None, None
  #############################################################################
  # TODO: Implement the backward pass for batch normalization. Store the      #
  # results in the dx, dgamma, and dbeta variables.                           #
  #                                                                           #
  # After computing the gradient with respect to the centered inputs, you     #
  # should be able to compute gradients with respect to the inputs in a       #
  # single statement; our implementation fits on a single 80-character line.  #
  #############################################################################
  (x,x_mean,x_variance,x_normed,gamma,beta,eps) = cache
  N = x.shape[0]

  # Backward for gamma scaling and beta shifting
  dbeta = np.sum(dout,axis = 0)
  dgamma = np.sum(dout*x_normed,axis = 0)
  dx_normed = dout*gamma

  # Simplify the backward operations into variance, mean and x
  dx_variance = np.sum((-0.5)*(x_normed*dx_normed/(x_variance+eps)),axis = 0)
  dx_mean = np.sum((-1)*(1/np.sqrt(x_variance+eps)*dx_normed),axis = 0)
  dx = (1/np.sqrt(x_variance+eps))*dx_normed+(2/N)*dx_variance*(x-x_mean)+(1/N)*dx_mean
  #############################################################################
  #                             END OF YOUR CODE                              #
  #############################################################################

  return dx, dgamma, dbeta

def dropout_forward(x, dropout_param):
  """
  Performs the forward pass for (inverted) dropout.

  Inputs:
  - x: Input data, of any shape
  - dropout_param: A dictionary with the following keys:
    - p: Dropout parameter. We drop each neuron output with probability p.
    - mode: 'test' or 'train'. If the mode is train, then perform dropout;
      if the mode is test, then just return the input.
    - seed: Seed for the random number generator. Passing seed makes this
      function deterministic, which is needed for gradient checking but not in
      real networks.

  Outputs:
  - out: Array of the same shape as x.
  - cache: A tuple (dropout_param, mask). In training mode, mask is the dropout
    mask that was used to multiply the input; in test mode, mask is None.
  """
  p, mode = dropout_param['p'], dropout_param['mode']
  if 'seed' in dropout_param:
    np.random.seed(dropout_param['seed'])

  mask = None
  out = None

  if mode == 'train':
    ###########################################################################
    # TODO: Implement the training phase forward pass for inverted dropout.   #
    # Store the dropout mask in the mask variable.                            #
    ###########################################################################
    mask = (np.random.rand(*x.shape)<(1-p))/(1-p)
    out = x*mask
    ###########################################################################
    #                            END OF YOUR CODE                             #
    ###########################################################################
  elif mode == 'test':
    ###########################################################################
    # TODO: Implement the test phase forward pass for inverted dropout.       #
    ###########################################################################
    out = x
    ###########################################################################
    #                            END OF YOUR CODE                             #
    ###########################################################################

  cache = (dropout_param, mask)
  out = out.astype(x.dtype, copy=False)

  return out, cache

def dropout_backward(dout, cache):
  """
  Perform the backward pass for (inverted) dropout.

  Inputs:
  - dout: Upstream derivatives, of any shape
  - cache: (dropout_param, mask) from dropout_forward.
  """
  dropout_param, mask = cache
  mode = dropout_param['mode']

  dx = None
  if mode == 'train':
    ###########################################################################
    # TODO: Implement the training phase backward pass for inverted dropout.  #
    ###########################################################################
    dx = dout*mask
    ###########################################################################
    #                            END OF YOUR CODE                             #
    ###########################################################################
  elif mode == 'test':
    dx = dout
  return dx

def conv_forward_naive(x, w, b, conv_param):
  """
  A naive implementation of the forward pass for a convolutional layer.

  The input consists of N data points, each with C channels, height H and width
  W. We convolve each input with F different filters, where each filter spans
  all C channels and has height HH and width WW.

  Input:
  - x: Input data of shape (N, C, H, W)
  - w: Filter weights of shape (F, C, HH, WW)
  - b: Biases, of shape (F,)
  - conv_param: A dictionary with the following keys:
    - 'stride': The number of pixels between adjacent receptive fields in the
      horizontal and vertical directions.
    - 'pad': The number of pixels that will be used to zero-pad the input.

  Returns a tuple of:
  - out: Output data, of shape (N, F, H', W') where H' and W' are given by
    H' = 1 + (H + 2 * pad - HH) / stride
    W' = 1 + (W + 2 * pad - WW) / stride
  - cache: (x, w, b, conv_param)
  """
  out = None
  #############################################################################
  # TODO: Implement the convolutional forward pass.                           #
  # Hint: you can use the function np.pad for padding.                        #
  #############################################################################
  N,C,H,W = x.shape
  F,_,HH,WW = w.shape
  pad = conv_param['pad']
  stride = conv_param['stride']
  H_prime = int(((H-HH+2*pad)/stride)+1)
  W_prime = int(((W-WW+2*pad)/stride)+1)
  out = np.zeros((N,F,H_prime,W_prime))

  # Padding
  x_pad = np.zeros((N,C,H+2*pad,W+2*pad))
  for n in range(N):
      for c in range(C):
          x_pad[n,c] = np.pad(x[n,c],(pad,pad),'constant',constant_values = (0,0))

  # For every sample
  for n in range(N):
      # For every row and column of an activation map
      for h_prime in range(H_prime):
          for w_prime in range(W_prime):
              # For every filter
              for f in range(F):
                  current_x = x_pad[n,:,h_prime*stride:h_prime*stride+HH,w_prime*stride:w_prime*stride+WW]
                  current_w = w[f]
                  out[n,f,h_prime,w_prime] = np.sum(current_x*current_w)
              out[n,:,h_prime,w_prime] += b
  #############################################################################
  #                             END OF YOUR CODE                              #
  #############################################################################
  cache = (x, w, b, conv_param)
  return out, cache

def conv_backward_naive(dout, cache):
  """
  A naive implementation of the backward pass for a convolutional layer.

  Inputs:
  - dout: Upstream derivatives.
  - cache: A tuple of (x, w, b, conv_param) as in conv_forward_naive

  Returns a tuple of:
  - dx: Gradient with respect to x
  - dw: Gradient with respect to w
  - db: Gradient with respect to b
  """
  dx, dw, db = None, None, None
  #############################################################################
  # TODO: Implement the convolutional backward pass.                          #
  #############################################################################
  x,w,b,conv_param = cache
  pad = conv_param['pad']
  stride = conv_param['stride']
  N,C,H,W = x.shape
  _,F,H_prime,W_prime = dout.shape
  _,_,HH,WW = w.shape
  db = np.zeros((F))
  dw = np.zeros((F,C,HH,WW))
  dx_pad = np.zeros((N,C,H+2*pad,W+2*pad))

  # Padding
  x_pad = np.zeros((N,C,H+2*pad,W+2*pad))
  for n in range(N):
      for c in range(C):
          x_pad[n,c] = np.pad(x[n,c],(pad,pad),'constant',constant_values = (0,0))

  # db -- fix F dimension and sume all the other values in corresponding dimensions in dout
  for n in range(N):
      for h_prime in range(H_prime):
          for w_prime in range(W_prime):
              db += dout[n,:,h_prime,w_prime]

  # dw -- spatial version is an extension of what we have developed above
  for n in range(N):
      for f in range(F):
          for h_prime in range(H_prime):
              for w_prime in range(W_prime):
                  current_x = x_pad[n,:,h_prime*stride:h_prime*stride+HH,w_prime*stride:w_prime*stride+WW]
                  dw[f] += dout[n,f,h_prime,w_prime]*current_x
                  dx_pad[n,:,h_prime*stride:h_prime*stride+HH,w_prime*stride:w_prime*stride+WW] += dout[n,f,h_prime,w_prime]*w[f]

  dx = dx_pad[:,:,pad:H+pad,pad:W+pad]
  #############################################################################
  #                             END OF YOUR CODE                              #
  #############################################################################
  return dx, dw, db

def max_pool_forward_naive(x, pool_param):
  """
  A naive implementation of the forward pass for a max pooling layer.

  Inputs:
  - x: Input data, of shape (N, C, H, W)
  - pool_param: dictionary with the following keys:
    - 'pool_height': The height of each pooling region
    - 'pool_width': The width of each pooling region
    - 'stride': The distance between adjacent pooling regions

  Returns a tuple of:
  - out: Output data
  - cache: (x, pool_param)
  """
  out = None
  #############################################################################
  # TODO: Implement the max pooling forward pass                              #
  #############################################################################
  N,C,H,W = x.shape
  pool_height = pool_param['pool_height']
  pool_width = pool_param['pool_width']
  stride = pool_param['stride']
  H_out = int(((H-pool_height)/stride)+1)
  W_out = int(((W-pool_width)/stride)+1)
  out = np.zeros((N,C,H_out,W_out))
  # For every sample
  for n in range(N):
      # For every filter
      for c in range(C):
          # For every row and column of a pooling map
          for h in range(H_out):
              for w in range(W_out):
                  current_x = x[n,c,h*stride:h*stride+pool_height,w*stride:w*stride+pool_width]
                  out[n,c,h,w] = np.max(current_x)
  #############################################################################
  #                             END OF YOUR CODE                              #
  #############################################################################
  cache = (x, pool_param)
  return out, cache

def max_pool_backward_naive(dout, cache):
  """
  A naive implementation of the backward pass for a max pooling layer.

  Inputs:
  - dout: Upstream derivatives
  - cache: A tuple of (x, pool_param) as in the forward pass.

  Returns:
  - dx: Gradient with respect to x
  """
  dx = None
  #############################################################################
  # TODO: Implement the max pooling backward pass                             #
  #############################################################################
  x,pool_param = cache
  N,C,H_out,W_out = dout.shape
  pool_height = pool_param['pool_height']
  pool_width = pool_param['pool_width']
  stride = pool_param['stride']
  dx = np.zeros(x.shape)

  # For every sample
  for n in range(N):
      # For every filter
      for c in range(C):
          # For every row and column of a pooling map
          for h in range(H_out):
              for w in range(W_out):
                  current_x = x[n,c,h*stride:h*stride+pool_height,w*stride:w*stride+pool_width]
                  argmax_indices = np.unravel_index(current_x.argmax(),current_x.shape)
                  dx[n,c,h*stride+argmax_indices[0],w*stride+argmax_indices[1]] += dout[n,c,h,w]
  #############################################################################
  #                             END OF YOUR CODE                              #
  #############################################################################
  return dx

def spatial_batchnorm_forward(x, gamma, beta, bn_param):
  """
  Computes the forward pass for spatial batch normalization.

  Inputs:
  - x: Input data of shape (N, C, H, W)
  - gamma: Scale parameter, of shape (C,)
  - beta: Shift parameter, of shape (C,)
  - bn_param: Dictionary with the following keys:
    - mode: 'train' or 'test'; required
    - eps: Constant for numeric stability
    - momentum: Constant for running mean / variance. momentum=0 means that
      old information is discarded completely at every time step, while
      momentum=1 means that new information is never incorporated. The
      default of momentum=0.9 should work well in most situations.
    - running_mean: Array of shape (D,) giving running mean of features
    - running_var Array of shape (D,) giving running variance of features

  Returns a tuple of:
  - out: Output data, of shape (N, C, H, W)
  - cache: Values needed for the backward pass
  """
  out, cache = None, None

  #############################################################################
  # TODO: Implement the forward pass for spatial batch normalization.         #
  #                                                                           #
  # HINT: You can implement spatial batch normalization using the vanilla     #
  # version of batch normalization defined above. Your implementation should  #
  # be very short; ours is less than five lines.                              #
  #############################################################################
  N,C,H,W = x.shape
  # Transform (N,C,H,W) to (N,W,H,C)
  x_permuted = x.transpose(0,3,2,1)
  # Reshape (N,W,H,C) to (N*W*H,C), in order to perform (N,D) batch normalization where D remains unchanged after transformation
  x_permuted_reshaped = x_permuted.reshape((N*W*H,C))
  out_unshaped,cache = batchnorm_forward(x_permuted_reshaped,gamma,beta,bn_param)
  out = out_unshaped.reshape(N,W,H,C).transpose(0,3,2,1)
  #############################################################################
  #                             END OF YOUR CODE                              #
  #############################################################################

  return out, cache

def spatial_batchnorm_backward(dout, cache):
  """
  Computes the backward pass for spatial batch normalization.

  Inputs:
  - dout: Upstream derivatives, of shape (N, C, H, W)
  - cache: Values from the forward pass

  Returns a tuple of:
  - dx: Gradient with respect to inputs, of shape (N, C, H, W)
  - dgamma: Gradient with respect to scale parameter, of shape (C,)
  - dbeta: Gradient with respect to shift parameter, of shape (C,)
  """
  dx, dgamma, dbeta = None, None, None

  #############################################################################
  # TODO: Implement the backward pass for spatial batch normalization.        #
  #                                                                           #
  # HINT: You can implement spatial batch normalization using the vanilla     #
  # version of batch normalization defined above. Your implementation should  #
  # be very short; ours is less than five lines.                              #
  #############################################################################
  N,C,H,W = dout.shape
  # Transform (N,C,H,W) to (N,W,H,C)
  dout_permuted_reshaped = dout.transpose(0,3,2,1).reshape((N*W*H,C))
  # Reshape (N,W,H,C) to (N*W*H,C), in order to perform (N,D) batch normalization where D remains unchanged after backward operation
  dx_unshaped,dgamma,dbeta = batchnorm_backward_alt(dout_permuted_reshaped,cache)
  dx = dx_unshaped.reshape(N,W,H,C).transpose(0,3,2,1)
  #############################################################################
  #                             END OF YOUR CODE                              #
  #############################################################################

  return dx, dgamma, dbeta

def svm_loss(x, y):
  """
  Computes the loss and gradient using for multiclass SVM classification.

  Inputs:
  - x: Input data, of shape (N, C) where x[i, j] is the score for the jth class
    for the ith input.
  - y: Vector of labels, of shape (N,) where y[i] is the label for x[i] and
    0 <= y[i] < C

  Returns a tuple of:
  - loss: Scalar giving the loss
  - dx: Gradient of the loss with respect to x
  """
  N = x.shape[0]
  correct_class_scores = x[np.arange(N), y]
  margins = np.maximum(0, x - correct_class_scores[:, np.newaxis] + 1.0)
  margins[np.arange(N), y] = 0
  loss = np.sum(margins) / N
  num_pos = np.sum(margins > 0, axis=1)
  dx = np.zeros_like(x)
  dx[margins > 0] = 1
  dx[np.arange(N), y] -= num_pos
  dx /= N
  return loss, dx

def softmax_loss(x, y):
  """
  Computes the loss and gradient for softmax classification.

  Inputs:
  - x: Input data, of shape (N, C) where x[i, j] is the score for the jth class
    for the ith input.
  - y: Vector of labels, of shape (N,) where y[i] is the label for x[i] and
    0 <= y[i] < C

  Returns a tuple of:
  - loss: Scalar giving the loss
  - dx: Gradient of the loss with respect to x
  """
  probs = np.exp(x - np.max(x, axis=1, keepdims=True))
  probs /= np.sum(probs, axis=1, keepdims=True)
  N = x.shape[0]
  loss = -np.sum(np.log(probs[np.arange(N), y])) / N
  dx = probs.copy()
  dx[np.arange(N), y] -= 1
  dx /= N
  return loss, dx


#!/usr/bin/env python
"""
Solves and visualizes LQR solution using traditional Ricatti Equation as a "ground truth"
    comparison.
Author: Gerry Chen, Yetong Zhang, and Frank Dellaert
"""
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.lines import Line2D

def ricatti_update(P, A, B, Q, R, N=None):
    '''Calculates next cost-to-go matrix, P, according to the Discrete Algebraic Ricatti Equation.
    See
    https://en.wikipedia.org/wiki/Linear%E2%80%93quadratic_regulator#Finite-horizon,_discrete-time_LQR
    Arguments:
        P: Previous cost-to-go matrix
        A: state transition matrix
        B: input matrix
        Q: state cost matrix
        R: control cost matrix
        N: cross-term cost matrix
    Returns:
        Pnew: new cost-to-go matrix
        K: control law for new timestep
    '''
    if not N:
        N = np.zeros((np.size(R, 0), np.size(Q, 0)))
    AT = A.transpose()
    BT = B.transpose()
    NT = N.transpose()
    if (R + BT*P*B).ndim == 1:
        inverse_term = 1/(R + BT*P*B)
    else:
        inverse_term = np.linalg.inv(R + BT*P*B)
    K = (AT*P*B + N)*inverse_term
    Pnew = (AT*P*A -
            K*(BT*P*A + NT) +
            Q)
    return Pnew, K

def get_k_and_p_ricatti(T, A, B, Q, R, N=None):
    '''Calculates the control gain, K, and cost-to-go, V, for each time step of a finite horizon LQR
    problem.
    Arguments:
        T: number of time steps
        A: state transition matrix
        B: input matrix
        Q: state cost matrix
        R: control cost matrix
        N: cross-term cost matrix
    Returns:
        K: optimal control law for each time step
        P: cost-to-go for each time step (aka V)
    '''
    P = np.zeros((T, 1))
    K = np.zeros((T-1, 1))
    P[-1] = Q
    for t in range(T-1, 0, -1):
        P[t-1], K[t-1] = ricatti_update(P[t], A, B, Q, R, N)
    return K, P

def visualize_cost(A, B, K, P, fig=None, plottype='heatmap', title='Return Cost'):
    '''Plots the cost-to-go and control law.
    Arguments:
        A: state transition matrix (nxn)
        B: input control matrix (nxp)
        K: optimal control law at each time step (Txn)
        P: cost-to-go at each time step (Tx1)
        fig: optional matplotlib figure/subfigure in which to plot
        plottype: either 'heatmap' or 'level sets'.  If 'heatmap', plots a heatmap of cost-to-go
            with vectors indicating optimal control direction and an example trajectory.  If 'level
            sets', plots level sets of the cost-to-go with state on x-axis, cost on y-axis, and time
            step being parameterized.
        title: optional title of plot
    '''
    T = np.size(K, 0)
    x_vals = np.linspace(-10, 10, 100)
    t_vals = range(T)
    cost_vals = x_vals.transpose()*P*x_vals

    if not fig:
        plt.figure(figsize=(6, 5))

    if plottype == 'heatmap':
        # heat map cost function
        plt.imshow(cost_vals, origin='lower',
                   extent=(x_vals[0], x_vals[-1], t_vals[0], t_vals[-1]),
                   aspect='auto')
        plt.xlabel('x')
        plt.ylabel('time step')
        plt.colorbar().set_label('Cost-to-go')

        # plot quivers
        quiver_inds = slice(0, len(K), 5)
        x_vals_quiver = np.linspace(x_vals[0], x_vals[-1], 15)
        t_vals_quiver = t_vals[quiver_inds]
        u_vals_quiver = -K[quiver_inds]*x_vals_quiver
        q = plt.quiver(x_vals_quiver, t_vals_quiver,
                       B*u_vals_quiver, np.ones(np.shape(u_vals_quiver)), angles='xy')
        plt.quiverkey(q, X=0.07, Y=1.03, U=2,
                      label='Optimal Control Direction', labelpos='E')

        # plot example trajectories
        trajectories = np.zeros((len(t_vals), 3))
        trajectories[0, :] = [x_vals[0], -3, 8]
        for t in range(0, t_vals[-2]):
            u_tmp = - K[t] * trajectories[t, :]
            trajectories[t+1, :] = A*trajectories[t, :] + B*u_tmp
        plt.plot(trajectories, t_vals, 'r-')
        plt.legend(('Example trajectories',), loc="upper right")
    elif plottype == 'level sets':
        # cost function level sets
        cm = plt.cm.copper
        plt.gca().set_prop_cycle(plt.cycler('color',
                                            cm(np.linspace(0, 1, np.size(cost_vals, 0)))))
        plt.plot(x_vals, cost_vals.transpose())
        plt.xlabel('x')
        plt.ylabel('Return cost')
        num_lines = 8
        custom_lines = [Line2D([0], [0], color=cm(i/num_lines), lw=4)
                        for i in range(num_lines)]
        plt.legend(custom_lines, np.linspace(t_vals[0], t_vals[-1], num_lines, dtype=int),
                   title="time step")
    else:
        raise ValueError("plottype must be either 'heatmap' or 'level sets'")

    if title:
        plt.title(title)

def main():
    '''Creates and solves a simple 1D system where the control is particle velocity and state is
    particle position.  Solves LQR problem using Ricatti Equation and plots cost-to-go.
    '''
    A = np.array([1.1])
    B = np.array([0.1])
    Q = np.array([2.])
    R = np.array([1.])
    N = np.array([0.])

    T = 50
    K, P = get_k_and_p_ricatti(T, A, B, Q, R, N)

    plt.figure(figsize=(12, 5))
    visualize_cost(A, B, K, P, fig=plt.subplot(1, 2, 1), title=None, plottype='heatmap')
    visualize_cost(A, B, K, P, fig=plt.subplot(1, 2, 2), title=None, plottype='level sets')
    plt.suptitle('Return cost assuming LQR control for a massless particle '+
                 'moving through molasses (1-D)')
    plt.show()

if __name__ == '__main__':
    main()


import torch
import numpy as np
from Deep_Learning_from_Scratch.ch04.LossFunctions import torch_cross_entropy_error
# from Deep_Learning_from_Scratch.ch04.NumericalDiff import numerical_gradient

def numerical_gradient(f, x):
    h = 1e-4  # 0.0001
    grad = torch.zeros_like(x).to(dtype=torch.float64)

    it = np.nditer(x, flags=['multi_index'], op_flags=['readwrite'])
    while not it.finished:
        idx = it.multi_index
        tmp_val = x[idx].item()
        x[idx] = tmp_val + h
        fxh1 = f(x)  # f(x+h)

        x[idx] = tmp_val - h
        fxh2 = f(x)  # f(x-h)
        grad[idx] = (fxh1 - fxh2) / (2 * h)

        x[idx] = tmp_val  # 값 복원
        it.iternext()

    return grad

class simpleNet:
    def __init__(self):
        self.W = torch.randn(2, 3).to(dtype=torch.float64)

    def predict(self, x):
        return x@self.W

    def fn_softMax(self, a):
        c = torch.max(a)
        return torch.exp(a - c) / torch.sum(torch.exp(a - c))

    def loss(self, x, t):
        z = self.predict(x)
        y = self.fn_softMax(z)
        loss = torch_cross_entropy_error(y, t)
        return loss

net = simpleNet()
print(net.W)

x = torch.tensor([0.6, 0.9], dtype=torch.float64)
p = net.predict(x)
print(p)
print(p.argmax())

t = torch.tensor([0, 0, 1])
print(net.loss(x, t))

f = lambda w: net.loss(x, t)
dW = numerical_gradient(f, net.W)
print(dW)


import numpy as np

# Define a main() function that transpose matrix and
# create view array containing only 2nd and 4th row.
def main():
    arr = np.arange(1, 16).reshape(3, 5)
    arr_transpose = arr.T
    print(arr_transpose)

    second_and_forth_row_arr = arr_transpose[[1, 3], :]
    print(second_and_forth_row_arr)

# This is the standard boilerplate that calls the main() function.
if __name__ == '__main__':
    main()


import numpy as np

class Sigmoid():
    """
    Numerically stable sigmoid function.

    Parameters
    ----------
    x: array_like
        Input value(s).

    Returns
    -------
    out: ndarray or scalar
        Element-wise sigmoid of x.
    """
    def _positive_sigmoid(self, x):
        out = 1 / (1 + np.exp(-x))
        return out

    def _negative_sigmoid(self, x):
        exp = np.exp(x)
        out = exp / (exp + 1)
        return out

    def __call__(self, x):

        # Identify positive and negative values
        positive_values = x >= 0
        negative_values = ~positive_values

        # Calculate numerically stable sigmoid of given array
        out = np.zeros(x.shape)
        out[positive_values] = self._positive_sigmoid(x[positive_values])
        out[negative_values] = self._negative_sigmoid(x[negative_values])

        return out