'''
This code file contains all the functions for implementation of gradient
descent on a custom function. The comments and docstrings explain the code,
but for a more detailed explanation, please go through the Readme.md file
in this folder.

'''

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

def func(x):
  '''
    We want to model our dataset on the sine function as it has some amount
    of complexity.
  '''
  return np.sin(x)

def create_dataset(n):
  x = np.linspace(0,10,num=n)
  # instead of using the sine function on its own, we are adding noise randomly
  y = func(x)+np.random.randn(n)*0.1
  return x,y

def show_dataset(x,y):
    # This function just displays the dataset
    a = np.linspace(0,10,num=70)
    plt.plot(a,np.sin(a),color='green')
    plt.scatter(x,y)
    plt.show()

def gradient(f,w,x,y,h,val):
  # This function is used to calculate gradients of the loss function for a certain weight.
  b,yhat = f(y,x,w)
  w[val]+=h
  a,yhat = f(y,x,w)
  g = (a-b)/h
  return g,yhat

def predict(x,w):
    #This function is useful for predicting results.
  x_v = [x**i for i in range(len(w))]
  return np.dot(x_v,w)

def loss(y,x,w):
  # We would be using Mean squared error as the loss function
  yhat = [predict(x,w) for x in x]
  l = sum((y-yhat)**2) / len(w)
  return l,yhat

def model_creation(lossfn,x,y,w,learning_rate,epoch):
  # This is a generic function for creating the model
  t=time.time()
  loss2=[]
  print(lossfn(y,x,w))
  yhat=[]
  grads=[0,0,0,0]
  for i in range(epoch):
    #print(grads)
    j=0
    while(j<4):
      grads[j],yhat = gradient(lossfn,w,x,y,0.0000000001,j) #calculating gradients
      j+=1
    j=0
    #print(grads)
    while(j<4):
      w[j]-= learning_rate*grads[j]  #updating weights
      j+=1
    l,_= lossfn(y,x,w)
    loss2.append(l)
    if i%1000 == 0:
      print("Loss at epoch {} is {}".format(i,l)) #prints loss for every 1000 epochs
  print("Loss at epoch {} is {}".format(epoch,l))
  return loss2,yhat

def show_output(x,y,yhat):
    a = np.linspace(0,10,num=70)
    plt.plot(a,np.sin(a),color='green')
    plt.scatter(x,y,color='black')
    plt.scatter(x,yhat,color='red')
    plt.plot(x,yhat)
    plt.show()

if __name__ == '__main__':
    # Here is the driver code
    w_vector = np.random.randn(4)
    # We will be fitting a 3 degree polynomial
    x,y = create_dataset(30)
    # The above line creates the dataset and the line below displays it.
    show_dataset(x,y)
    # The model is trained
    l,yhat = model_creation(loss,x,y,w_vector,1e-7,50000)
    #The results are shown
    show_output(x,y,yhat)


import numpy as np
from scipy.linalg import solve

input_layer = np.array([1,2,3])

hidden_layer_1 = np.array([1,1,-5])

hidden_layer_2 = np.array([3,-4,2])

out_layer = np.array([2,-1])

node_1 = input_layer[0] * hidden_layer_1[0] + input_layer[1] * hidden_layer_1[1] + + input_layer[2] * hidden_layer_1[2]
node_2 = input_layer[0] * hidden_layer_2[0] + input_layer[1] * hidden_layer_2[1] + + input_layer[2] * hidden_layer_2[2]

print node_1
print node_2

node_3 = node_1 * out_layer[0] + node_2 * out_layer[1]

print node_3

dot1 = np.dot(input_layer, hidden_layer_1)
dot2 = np.dot(input_layer, hidden_layer_2)

print dot1
print dot2

for input_layer in np.array([[1,1],[0.5,0.5],[0.25,0.25],[-2,15]]):
# input_layer = np.array([1,1])
	print "New\n\n"
	hidden_layer_1 = np.array([3,2])

	hidden_layer_2 = np.array([-1,4])

	hidden_layer_3 = np.array([3,-5])

	dot1 = np.dot(input_layer, hidden_layer_1)
	dot2 = np.dot(input_layer, hidden_layer_2)
	dot3 = np.dot(input_layer, hidden_layer_3)

	print dot1
	print dot2
	print dot3

# print "New\n\n"

# input_layer = np.array([0.45,0.45])

# hidden_layer_1 = np.array([3,2])

# hidden_layer_2 = np.array([-1,4])

# hidden_layer_3 = np.array([3,-5])

# dot1 = np.dot(input_layer, hidden_layer_1)
# dot2 = np.dot(input_layer, hidden_layer_2)
# dot3 = np.dot(input_layer, hidden_layer_3)

# print dot1
# print dot2
# print dot3
import numpy as np
from scipy.linalg import solve

a = np.array([[3,2],[-1,4],[3,-5]])
b = np.array([1,2,-1])
#x ,resd, rnk, s = np.linalg.lstsq(a,b)
x = solve(a,b)

print x
print resd
print rnk
print s

# x_1 = np.allclose(np.dot(a,x), b)

# print x_1


import numpy as np

def get_phi(row):
    """Helper function for rotating data.

    row: 2D-entry in matrix with shape (?, 2)
    """
    return np.arctan2(row[0], row[1])

def rotate_2D(d, angle):
    """Rotate a 2-dimensional figure.

    Parameters
    ============

    d: the 2-dimensional data to rotate
    angle: the angle (in radians) to rotate the data around 0
    centered_around_zero: Boolean specifying whether the data is centered around zero.
    """
    try:
        assert d.shape[1] == 2
    except AssertionError:
        raise ValueError(
            "Error: data has {} dimensions, but should only be 2. ".format(d.shape[1])
        )

    rot = angle - np.pi / 2
    phis = np.apply_along_axis(get_phi, 1, d)
    phi_new = phis + rot
    r = np.sqrt(d[:, 0] ** 2 + d[:, 1] ** 2)

    x = r * np.cos(phi_new)
    y = r * np.sin(phi_new)
    return np.concatenate((x.reshape(-1, 1), y.reshape(-1, 1)), axis=1)


import numpy as np
from functools import reduce
def cov_cond(c,a):
    """生成条件数为c，第一主元方向向量为a的协方差矩阵
    Input:
    c: 条件数， int
    a: 第一主元方向向量， shape=(dim,1)
    Output:
    sigma: 协方差矩阵 ， shape=(dim,dim)
    preci: 精度矩阵
    """
    dim = a.shape[0]   # 获取维度
    e = np.sort(1/np.linspace(1, c, dim))   # 特征值
    a_div_norm = a/np.linalg.norm(a, axis=0)
    z = np.eye(dim) - 2.0*a_div_norm.dot(a_div_norm.T) # 构建豪斯霍尔德矩阵
    sigma = reduce(np.dot, (z, np.diag(e), z.T))
    preci = reduce(np.dot, (z, np.linalg.inv(np.diag(e)), z.T))
    return sigma, preci

if __name__ == "__main__":
    c = 10; a = np.random.randn(50)[:,np.newaxis]
    sigma, _ = cov_cond(c, a)
    print(np.linalg.cond(sigma, 2))


# =========================================================================
#
#    Graduate Course: Finite Element Analysis - Spring 2022 @JBNU
#
#  ========================================================================
#
#   Problem 1: A spring system
#
#   Last updated: 14/03/2022 by Minh-Chien Trinh (mctrinh@jbnu.ac.kr)
#
#   Copyright 2022 Minh-Chien Trinh. All rights reserved.
#
# =========================================================================

import numpy as np

# Element nodes
eNode = np.array([[1,2], [2,3], [2,4]])

# Number of elements
nElem = np.size(eNode,0)                # axis=0 returns the number of row

# Number of nodes
nNode = 4

# Initialization
Umat = np.zeros((nNode,1))              # Displacement vector
Fmat = np.zeros((nNode,1))              # Force vector
Kmat = np.zeros((nNode,nNode))          # Stiffness matrix
# Applied load at node 2
Fmat[1,0] = 10                          # Python index from 0

for i in range(nElem):
    # Element degree of freedom
    eDof = eNode[i,:]

    # Row index
    rIndex = np.zeros((np.size(eDof),np.size(eDof)), dtype=int)
    rIndex[0:2,0] = eDof - 1
    rIndex[0:2,1] = eDof - 1

    # Column index
    cIndex = np.zeros((np.size(eDof),np.size(eDof)), dtype=int)
    cIndex[0,0:2] = eDof - 1
    cIndex[1,0:2] = eDof - 1

    # The contribution of the element to the stiffness matrix
    Kmat[rIndex,cIndex] = Kmat[rIndex,cIndex] + np.array([[1,-1], [-1, 1]])

# Apply boundary condition
# Fix/prescribed degree of freedom
fixDof = np.array([[0], [2], [3]])
# Free/active degree of freedom
activeDof = np.setdiff1d(np.arange(0,nNode,1), fixDof)

# Solution
# Indexing of activeDof
iIndex = np.zeros((1,1), dtype=int)
iIndex[0,0] = activeDof
jIndex = np.zeros((1,1), dtype=int)
jIndex[0,0] = activeDof
# Evaluate displacement at activeDof
Umat[activeDof,0] = np.dot(np.linalg.inv(Kmat[iIndex,jIndex]),Fmat[activeDof,0])
print(Umat)

# Force vector
Fmat = np.dot(Kmat,Umat)
print(Fmat)

# Reactions
Reaction = np.zeros(np.size(fixDof))
Reaction = Fmat[fixDof,0]
print(Reaction)


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

"""AFN on correlated random time series.

The AFN algorithm is not impervious to correlated stochastic data.
Here we use a time series coming from an AR(1) process and see that the
E2(d) curve has a nontrivial appearance, falsely giving the appearance
of determinism.

Two points are to be noted:

1. Although the E2(d) curves have a nontrivial appearance, they are
   different from the curves seen for deterministic data.  Here the
   value of E2(d) first decreases with d and then increases, whereas
   for deterministic data, E2(d) is seen to increase right from the
   beginning.

2. Imposing a minimum temporal separation equal to the autocorrelation
   time of the series while searching for near neighbors solves the
   problem.
"""

from nolitsa import delay, dimension, utils
import matplotlib.pyplot as plt
import numpy as np

# Generate stochastic data.
N = 5 * 1000
x = np.empty(N)

np.random.seed(999)
eta = np.random.normal(size=(N), loc=0, scale=1.0)
a = 0.99

x[0] = eta[0]
for i in range(1, N):
    x[i] = a * x[i - 1] + eta[i]

x = utils.rescale(x)

# Calculate the autocorrelation time.
tau = np.argmax(delay.acorr(x) < 1.0 / np.e)

# AFN without any minimum temporal separation.
dim = np.arange(1, 10 + 2)
F, Fs = dimension.afn(x, tau=tau, dim=dim, window=0)
F1, F2 = F[1:] / F[:-1], Fs[1:] / Fs[:-1]

# AFN with a minimum temporal separation (equal to the autocorrelation
# time) between near-neighbors.
dim = np.arange(1, 10 + 2)
E, Es = dimension.afn(x, tau=tau, dim=dim, window=tau)
E1, E2 = E[1:] / E[:-1], Es[1:] / Es[:-1]

plt.figure(1)
plt.title(r'AR(1) process with $a = 0.99$')
plt.xlabel(r'i')
plt.ylabel(r'$x_i$')
plt.plot(x)

plt.figure(2)
plt.title(r'AFN without any minimum temporal separation')
plt.xlabel(r'Embedding dimension $d$')
plt.ylabel(r'$E_1(d)$ and $E_2(d)$')
plt.plot(dim[:-1], F1, 'bo-', label=r'$E_1(d)$')
plt.plot(dim[:-1], F2, 'go-', label=r'$E_2(d)$')
plt.legend()

plt.figure(3)
plt.title(r'AFN with a minimum temporal separation of $%d$' % tau)
plt.xlabel(r'Embedding dimension $d$')
plt.ylabel(r'$E_1(d)$ and $E_2(d)$')
plt.plot(dim[:-1], E1, 'bo-', label=r'$E_1(d)$')
plt.plot(dim[:-1], E2, 'go-', label=r'$E_2(d)$')
plt.legend()

plt.show()


# waves.py
# -----------------------------------------------------------------------------
# Generate frames for an animation of a moving Gaussian waves.
# -----------------------------------------------------------------------------
import numpy as np
import matplotlib.pyplot as plt
# get html_movie module from physicalmodelingwithpython.blogspot.com/
from html_movie import movie

# Generate waves for each frame.
# Return a gaussian with specified center and spread using array s.
def gaussian(s, center=0.0, spread=1.0):
	return np.exp(-2 * (s - center)**2 / spread**2)

# All lengths are in [m], all times are in [s], and all speeds are in [m/s].
# Define the range of values to display.
xmin, xmax  = -4.0, 4.0
ymin, ymax  = -3.0, 3.0
# Define array of positions.
dx = 0.01
x = np.arange(xmin, xmax + dx, dx)

# Define the duration and number of frames for the simulation.
tmin, tmax  = 0.0, 4.0
num_frames = 100
t = np.linspace(tmin, tmax, num_frames)

# Define the initial position and speed of gaussian waves.
r_speed = 2.0		# speed of right-moving wave
r_0 = -4.0			# initial position of right-moving wave
l_speed = -2.0		# speed of left-moving wave
l_0 = 4.0			# initial position of left-moving wave

# Generate a figure and get access to its axes object.
plt.close('all')
fig = plt.figure(figsize=(10,10))
ax = plt.axes(xlim=(xmin, xmax), ylim=(ymin, ymax))

# Create three empty line objects and grab control.
# The loop below will update the lines in each frame.
ax.plot([], [], 'b--', lw=1)		# line for right-moving wave
ax.plot([], [], 'r--', lw=1)		# line for left-moving wave
ax.plot([], [], 'g-', lw=3)			# line for sum of waves
lines = ax.get_lines()				# get list of 3 line objects in plot

# It is essential that the frames be named in alphabetical order.
# {:03d} will display integers with three digits and insert zeros if needed:
# '000_movie.jpg', '001_movie.jpg', etc.
file_name = "{:03d}_movie.jpg"

# Generate frames and save each figure as a separate .jpg file.
for i in range(num_frames):
	r_now = r_0 + r_speed * t[i]		# update center of right-moving wave
	l_now = l_0 + l_speed * t[i]		# update center of left-moving wave
	yR =  gaussian(x, r_now)			# get current data for right-moving wave
	yL = -gaussian(x, l_now)			# get current data for left-moving wave
	lines[0].set_data(x,yR)				# update right-moving wave
	lines[1].set_data(x,yL)				# update left-moving wave
	lines[2].set_data(x,yR + yL)		# update sum of waves
	plt.savefig(file_name.format(i))	# save current plot

# Use html movie encoder adapted from scitools to create an HTML document that
# will display the frames as a movie.  Open movie.html in Web browser to view.
movie(input_files='*.jpg', output_file='movie.html')


# Question 3 Algorithm 1 (inefficient) Lab Assignment 03
# @AB Satyaprakash, 180123062

# imports
from math import exp, sqrt
import numpy as np
import time

# functions ---------------------------------------------------------------------------

def recursion(n, K, S, T, r, sig, M, u, d, p, q, dt):

    if n == M:
        return max(S - K, 0)

    up = recursion(n + 1, K, S * u, T, r, sig, M, u, d, p, q, dt)
    dn = recursion(n + 1, K, S * d, T, r, sig, M, u, d, p, q, dt)
    pc = (exp(-r * dt)) * (p * up + q * dn)
    return pc

# -------------------------------------------------------------------------------------
# Given Initial Values -- and taking K = 100
S0, K, T, r, sig = 100, 100, 1, 0.08, 0.2
# Can't handle values of M beyond 20 ..
Mlist = [5, 10, 20]

for M in Mlist:
    dt = T/M

    u = exp(sig*sqrt(dt)+(r-sig*sig/2)*dt)
    d = exp(-sig*sqrt(dt)+(r-sig*sig/2)*dt)
    p = (exp(r*dt)-d)/(u-d)
    q = 1-p
    loopbackOptionPrice = recursion(0, K, S0, T, r, sig, M, u, d, p, q, dt)
    print('The initial european call option price for M = {} is {}'.format(M, loopbackOptionPrice))

# Test computation time for M = 15: ------------------------------------------------
dt = T/M
u = exp(sig*sqrt(dt)+(r-sig*sig/2)*dt)
d = exp(-sig*sqrt(dt)+(r-sig*sig/2)*dt)
p = (exp(r*dt)-d)/(u-d)
q = 1-p
start = time.time()
timeTempPrice = recursion(0, K, S0, T, r, sig, M, u, d, p, q, dt)
end = time.time()

print('Computational time for M = 15 is {}s'.format(end-start))

# Question 3 algorithm 1 ends -------------------------------------------------------------

Semester 6/MA 374 (Financial Engg. Lab)/Lab 3/180123062_AB_q3_1.py


#!/usr/bin/env python
# -*- coding: utf8 -*-
"""
    @author lichuan89@126.com
    @date   2016/09/12
    @note
"""

import numpy as np
import copy

# 参考:
#   https://blog.csdn.net/cckchina/article/details/79915181
#   https://zhuanlan.zhihu.com/p/37740860

def logistic(z):
    o = copy.deepcopy(z)
    o[o > 0] = 1 / (1 + np.exp(-o[o > 0]))
    o[o <= 0] = np.exp(o[o <= 0]) / (1 + np.exp(o[o <= 0]))
    return o

def logistic_deriv(y):
    return np.multiply(y, (1 - y))

def softmax(z):
    return np.exp(z) / np.sum(np.exp(z), axis=1, keepdims=True)

def softmax_deriv(y):
    return np.multiply(y, (1 - y))

def relu(z):
    return np.maximum(z, 0)

def relu_deriv(y):
    o = np.ones(y.shape)
    o[y < 0] = 0
    return o

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

def tanh_deriv(y):
    return 1 - y ** 2

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

def arctan_deriv(z):
    return 1 / (1 + z ** 2)

def crossEntropy_cost(y, t):
    """
    交叉熵损失函数
    """
    o = copy.deepcopy(y)
    o[o < 1e-10] = 1e-10
    o[o > 0.99] = 1 - 1e-10
    return - np.multiply(t, np.log(o)).sum() / o.shape[0]

def crossEntropy_cost_deriv(y, t):
    """
    交叉熵损失函数对预测值y的梯度
    """
    return (y - t) / y / (1 - y) / y.shape[0]


import numpy as np
import scipy.stats as sp

def cosd(angle):
    """Compute cosine of angle in degrees.

    Parameters
    ----------
    angle: float
        Angle in degrees
    """

    return np.cos(np.pi * angle/180)

def sind(angle):
    """Compute sine of angle in degrees.

        Parameters
        ----------
        angle: float
            Angle in degrees
        """

    return np.sin(np.pi * angle/180)

def tand(angle):
    """Compute tangent of angle in degrees.

        Parameters
        ----------
        angle: float
            Angle in degrees
        """

    return np.tan(np.pi * angle/180)

def arctand(angle):
    """Compute arctangent of angle in degrees.

        Parameters
        ----------
        angle: float
            Angle in degrees
        """

    return np.arctan(angle) * 180/np.pi

def cart2pol(x, y):
    """Convert cartesian coordinates to polar coordinates.

    Parameters
    ----------
    x: float
        x coordinate
    y: float
        y coordinate

    Returns
    -------
    phi: float
        Angle in radians
    rho: float
        Magnitude
    """

    rho = np.sqrt(x**2 + y**2)
    phi = np.arctan2(y, x)

    return phi, rho

def pol2cart(phi, rho):
    """Convert polar coordinates to cartesian coordinates.

        Parameters
        ----------
        phi: float
            Angle in radians
        rho: float
            Magnitude

        Returns
        -------
        x: float
            x coordinate
        y: float
            y coordinate

        """

    x = rho * np.cos(phi)
    y = rho * np.sin(phi)

    return x, y

def iqr(data):
    """This function computes the iqr consistent with Matlab

    Parameters
    ----------
    data: np.ndarray
        Data for which the statistic is required

    Returns
    -------
    sp_iqr: float
        Inner quartile range

    """

    # If 2-D array use only 1st row
    if len(data.shape) > 1:
        data_1d = data.flatten()
    else:
        data_1d = data

    # Remove nan elements
    idx = np.where(np.isnan(data_1d) == False)[0]
    data_1d = data_1d[idx]

    # Compute statistics
    q25, q50, q75 = sp.mstats.mquantiles(data_1d, alphap=0.5, betap=0.5)
    sp_iqr = q75 - q25

    return sp_iqr

def iqr_2d(data):
    """This function computes the iqr consistent with Matlab

    Parameters
    ----------
    data: np.ndarray
        Data for which the statistic is required

    Returns
    -------
    sp_iqr: float
        Inner quartile range

    """

    # Remove nan elements
    data = np.array(data)
    idx = np.where(np.isnan(data) == False)[0]
    data = data[idx]

    # Compute statistics
    q25, q50, q75 = sp.mstats.mquantiles(data, alphap=0.5, betap=0.5)
    sp_iqr = q75 - q25
    return sp_iqr

def azdeg2rad(angle):
    """Converts an azimuth angle in degrees to radians.

    Parameters
    ----------
    angle: float, np.ndarray(float)
        Azimuth angle in degrees

    Returns
    -------
    direction: float, np.ndarray(float)
        Angle in radians
    """

    # Convert to radians
    direction = np.deg2rad(90-angle)

    # Create postive angle
    idx = np.where(direction < 0)[0]
    if len(idx) > 1:
        direction[idx] = direction[idx] + 2 * np.pi
    else:
        direction = direction + 2 * np.pi

    return direction

def rad2azdeg(angle):
    """Converts an angle in radians to an azimuth in degrees.

    Parameters
    ----------
    angle: float, np.ndarray(float)
        Angle in radians

    Returns
    -------
    deg: float, np.ndarray(float)
        Azimuth in degrees
    """

    if isinstance(angle, float):
        deg = np.rad2deg(angle)
        deg = 90 - deg
        if deg < 0:
            deg += 360

        return deg
    else:
        # Multiple values
        deg = np.rad2deg(angle)
        deg = 90 - deg
        sub_zero = np.where(deg < 0)
        deg[sub_zero] = deg[sub_zero] + 360

        return deg

def nandiff(values):
    """Computes difference in consecutive values with handling of nans.

    Parameters
    ----------
    values: np.ndarray()
        1-D array of numbers

    Returns
    -------
    final_values: np.ndarray()
        1-D array of differences of consecutive non nan numbers
    """

    final_values = []
    for n in range(len(values) - 1):
        # Check for nan and add nan to final values
        if np.isnan(values[n]):
            final_values.append(np.nan)
        else:
            # Search for next non nan number and compute difference
            i = n + 1
            while np.isnan(values[i]) and i < len(values) - 1:
                i += 1

            final_values.append(values[i] - values[n])

    return np.array(final_values)

def valid_number(data_in):
    """Check to see if data_in can be converted to float.

    Parameters
    ----------
    data_in: str
        String to be converted to float

    Returns
    -------
    data_out: float
        Returns a float of data_in or nan if conversion is not possible
    """

    try:
        data_out = float(data_in)
    except ValueError:
        data_out = np.nan
    return data_out

def nans(shape, dtype=float):
    """Create array of nans.

    Parameters
    ----------
    shape: tuple
        Shape of array to be filled with nans
    dtype: type
        Type of array

    Returns
    -------
    a: np.ndarray(float)
        Array of nan
    """
    a = np.empty(shape, dtype)
    a.fill(np.nan)
    return a

def checked_idx(transects):
    """Create list of transect indices of all checked transects.

    Parameters
    ----------
    transects: list
        List of TransectData objects

    Returns
    -------
    checked: list
        List of indices

    """
    checked = []
    for n, transect in enumerate(transects):
        if transect.checked:
            checked.append(n)

    return checked

def units_conversion(units_id='SI'):
    """Computes the units conversion from SI units used internally to the
    desired display units.

    Parameters
    ----------
    units_id: str
        String variable identifying units (English, SI) SI is the default.

    Returns
    -------
    units: dict
        dictionary of unit conversion and labels
    """

    if units_id == 'SI':
        units = {'L': 1,
                 'Q': 1,
                 'A': 1,
                 'V': 1,
                 'label_L': '(m)',
                 'label_Q': '(m3/s)',
                 'label_A': '(m2)',
                 'label_V': '(m/s)',
                 'ID': 'SI'}

    else:
        units = {'L': 1.0 / 0.3048,
                 'Q': (1.0 / 0.3048)**3,
                 'A': (1.0 / 0.3048)**2,
                 'V': 1.0 / 0.3048,
                 'label_L': '(ft)',
                 'label_Q': '(ft3/s)',
                 'label_A': '(ft2)',
                 'label_V': '(ft/s)',
                 'ID': 'English'}

    return units

def convert_temperature(temp_in, units_in, units_out):
    """Converts temperature from F to C or C to F.

    Parameters
    ==========
    temp_in: np.array
        temperature in units_in
    units_in: str
        C for Celcius or F for Fahrenheit
    units_out: str
        C for Celcius or F for Fahrenheit

    Returns
    =======
    temp_out: np.array
        temperature in units_out
    """

    temp_out = None
    if units_in == 'F':
        if units_out == 'C':
            temp_out = (temp_in - 32) * (5./9.)
        else:
            temp_out = temp_in

    elif units_in == 'C':
        if units_out == 'C':
            temp_out = temp_in
        else:
            temp_out = (temp_in * (9./5.)) + 32

    return temp_out


__author__ = 'mhan0'

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import json
path = 'ch02/usagov_bitly_data2012-03-16-1331923249.txt'
records = [json.loads(line) for line in open(path)]
records[0]
records[0]['tz']

time_zones = [rec['tz'] for rec in records if 'tz' in rec]
len(time_zones)

#This function return a dictionary includes counts and the terms
def get_counts(sequence):
    counts = {}
    for x in sequence:
        if x in counts:
            counts[x] += 1
        else:
            counts[x] = 1
    return counts

get_counts(time_zones)
len(set(time_zones))

from collections import defaultdict
def get_counts2(sequence):
    counts = defaultdict(int)
    for x in sequence:
        counts[x] += 1
    return counts

tz2 = get_counts2(time_zones)
tz2['America/New_York']

def top_counts(count_dict, n = 10):
    value_key_pairs = [(count, tz) for tz, count in count_dict.items()]
    value_key_pairs.sort()
    return value_key_pairs[-n:]
top_counts(tz2)

from collections import Counter
counts = Counter(time_zones)
counts.most_common(10)

from pandas import DataFrame, Series
import pandas as pd
frame = DataFrame(records)
frame['tz'][:10]
frame['a'][:10]

clean_tz = frame['tz'].fillna('Missing')
clean_tz[clean_tz == ''] = 'Unknown'
tz_counts = clean_tz.value_counts()
tz_counts[:10]

tz_counts[:10].plot(kind='barh', rot = 0)

cframe = frame[frame.a.notnull()]
operating_system = np.where(cframe['a'].str.contains('Windows'),'Windows','Not Windows')
operating_system[:5]
by_tz_os = cframe.groupby(['tz', operating_system])
agg_counts = by_tz_os.size().unstack().fillna(0)
agg_counts[:10]

indexer = agg_counts.sum(1).argsort()
indexer[:10]

count_subset = agg_counts.take(indexer)[-10:]
count_subset

count_subset.plot(kind='barh', stacked =True)
normed_subset = count_subset.div(count_subset.sum(1), axis =0)
normed_subset.plot(kind='barh',stacked = True)

# Movie Data Study
import pandas as pd
unames = ['user_id', 'gender', 'age', 'occupation', 'zip']
users = pd.read_table('ch02/movielens/users.dat', sep ='::', header = None, names = unames, engine = 'python')

unames = ['user_id', 'movie_id', 'rating', 'timestamp']
ratings = pd.read_table('ch02/movielens/ratings.dat', sep ='::', header = None, names = unames, engine = 'python')

unames = ['movie_id', 'title', 'genres']
movies = pd.read_table('ch02/movielens/movies.dat', sep ='::', header = None, names = unames, engine = 'python')

users[:5]
ratings[:5]
ratings[:5]

data = pd.merge(pd.merge(ratings,users), movies)
data
data.ix[0]

# C:\Users\mhan0\AppData\Local\Continuum\Anaconda3\lib\site-packages\pandas\util\decorators.py:81: FutureWarning: the 'rows' keyword is deprecated, use 'index' instead
#   warnings.warn(msg, FutureWarning)
mean_ratings = data.pivot_table('rating', index = 'title', columns = 'gender', aggfunc = 'mean')
mean_ratings[:10]

rating_by_title = data.groupby('title').size()
active_titles = rating_by_title.index[rating_by_title>= 250]

mean_ratings = mean_ratings.ix[active_titles]

top_female_ratings = mean_ratings.sort_index(by = 'F', ascending=False)
top_female_ratings[:10]

mean_ratings['diff'] = mean_ratings['M'] - mean_ratings['F']

sorted_by_diff = mean_ratings.sort_index(by = 'diff')

sorted_by_diff[:15]

sorted_by_diff[::-1][:15]

#The third case study:
names1880 = pd.read_csv('ch02/names/yob1880.txt', names = ['name', 'sex', 'births'])
names1880.groupby('sex').births.sum()
years = range(1880,2011)
pieces = []
columns = ['name','sex','births']

#The way to read many data
for year in years:
    path = 'ch02/names/yob%d.txt' % year
    frame = pd.read_csv(path, names = columns)

    frame['year'] = year
    pieces.append(frame)
names = pd.concat(pieces,ignore_index = True)

names

total_births = names.pivot_table('births', index = 'year', columns = 'sex', aggfunc = sum)
total_births.tail()
total_births.plot(title = 'Total births by sex and year')

names

def add_prop(group):
    births = group.births.astype(float)

    group['prop'] = births/births.sum()
    return group
names = names.groupby(['year','sex']).apply(add_prop)
names

def get_top1000(group):
    return group.sort_index(by= 'births', ascending= False)[:1000]
grouped = names.groupby(['year','sex'])
top1000 = grouped.apply(get_top1000)

pieces = []
for year, group in names.groupby(['year','sex']):
    pieces.append(group.sort_index(by='births', ascending=False)[:1000])
top1000 = pd.concat(pieces, ignore_index=True)

boys = top1000[top1000.sex == 'M']
girls = top1000[top1000.sex == 'F']

total_births = top1000.pivot_table('births', index = 'year', columns = 'name', aggfunc = sum)

subset = total_births[['John', 'Harry', 'Mary', 'Marilyn']]

subset.plot(subplots = True, figsize = (12, 10), grid = False, title= "Number of births per year")

table = top1000.pivot_table('prop', index = 'year', columns = 'sex', aggfunc = sum)
table.plot(title="Sum of table1000.prop by year and sex",
           yticks = np.linspace(0,1.2,13), xticks = range(1880, 2020, 10))
df = boys[boys.year== 2010]
df

prop_cumsum = df.sort_index(by='prop', ascending = False).prop.cumsum()
prop_cumsum[:10]
prop_cumsum.searchsorted(0.5)

df = boys[boys.year ==1900]

in1900 = df.sort_index(by='prop', ascending = False).prop.cumsum()

in1900.searchsorted(0.5)+1

def get_quantile_count(group, q = 0.5):
    group = group.sort_index(by='prop', ascending= False)
    return group.prop.cumsum().searchsorted(q)+1
diversity = top1000.groupby(['year','sex']).apply(get_quantile_count)
diversity = diversity.unstack('sex')
diversity.head()
#Could not to plot???
#diversity.plot(title="Number of popular names in top 50%")
#Here the type of data should be numeric to plot
df = diversity.replace(',', '', regex=True)
df = df.replace('-', 'NaN', regex=True).astype('float')
df.plot()

get_last_letter = lambda x: x[-1]
last_letters = names.name.map(get_last_letter)
last_letters.name = 'las_letter'

table = names.pivot_table('births', index = last_letters, columns = ['sex','year'], aggfunc= sum)

subtable = table.reindex(columns = [1910,1960,2010], level = 'year')

subtable.head()

subtable.sum()

letter_prop = subtable/subtable.sum().astype(float)

import matplotlib.pyplot as plt
fig, axes = plt.subplots(2, 1, figsize = (10,8))
letter_prop['M'].plot(kind = 'bar', rot = 0, ax = axes[0], title = 'Male')
letter_prop['F'].plot(kind = 'bar', rot = 0, ax = axes[1], title = 'Famale', legend = False)

letter_prop = table/table.sum().astype(float)

dny_ts = letter_prop.ix[['d','n','y'], 'M'].T

dny_ts.head()
dny_ts.plot()

#iPython
import random
data = {i: random.random() for i in range(7)}
data

from numpy.random import randn
data = {i:randn() for i in range(7)}
data

an_apple = 27
an_example =42

b = [1,2,3]

import datetime
datetime.date
# %run PythonforDATest.py

def add_numbers(a,b):
    """
    Add two numbers together
    Returns
    :param a:
    :param b:
    :return:
    """
    return a+b
# ?add_numbers()
# ??add_numbers()

#Report the execution time of statement
# %time
# %timeit
# %who
# %who_ls
# %whos
#
# %logstart
# %logstate
# %logon
#
# %bookmark db C:/Users/mhan0
# %cd db

from numpy.random import randn
def add_and_sum(x,y):
    added =x +y
    summed = added.sum(axis=1)
    return summed
def call_function():
    x = randn(1000,1000)
    y = randn(1000,1000)
    return add_and_sum(x,y)

# %run prof_mod

# NumPy
import numpy as np
data = [[ 0.9526, -0.246 , -0.8856],[ 0.5639, 0.2379, 0.9104]]
data+data
data*10

data1 = [6,7.5,8,0,1]
arr1 = np.array(data1)

data2 = [[1,2,3,4],[5,6,7,8]]

arr2 = np.array(data2)
arr2

arr2.ndim
arr2.shape

arr1.dtype
arr2.dtype

np.zeros(10)

np.zeros((3,6))

np.empty((2,3,2))

np.arange(15)

names = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'])

data = randn(7,4)

names
data

names == 'Bob'

data[names == 'Bob']

data[names == 'Bob',2:]

data[names == 'Bob',3]

names!='Bob'
data[-(names=='Bob')]
data

mask = (names == 'Bob')|(names =='Will')
mask

data[mask]

data[data<0] = 0
data

data[names != 'Joe'] = 7
data

arr = np.empty((8,4))
for i in range(8):
    arr[i] = i

arr
arr[[4,3,0,6]]
arr[[-3,-5,-7]]

points = np.arange(-5,5,0.01)
xs,ys = np.meshgrid(points,points)

import matplotlib as plt
# %pylab
z = np.sqrt(xs**2+ys**2)

z

plt.imshow(z, cmap=plt.cm.gray); plt.colorbar()
plt.title("Image plot of $\sqrt{x^2+y^2}$ for a grid of values")

import random
position = 0
walk = [position]
steps = 1000
for i in range(steps):
    step = 1 if random.randint(0, 1) else -1
    position += step
    walk.append(position)

# plot(walk)
from pandas import Series, DataFrame
import pandas as pd

#Series
obj = Series([4,7,-5,3])

obj.values
obj.index

obj2 = Series([4,7,-5,3], index = ['d','b','a','c'])
obj2.index
obj2['a']
'b' in obj2

'e' in obj2

sdata = {'Ohio': 35000, 'Texas':71000, 'Oregon':16000,'Utah':5000}
obj3 = Series(sdata)
obj3

states = ['California','Ohio','Oregon','Texas']
obj4 = Series(sdata,index = states)

pd.isnull(obj4)
obj4.values

obj3+obj4

obj4.name = 'population'
obj4.index.name = 'state'
obj4

data = {'state': ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada'],
'year': [2000, 2001, 2002, 2001, 2002],
'pop': [1.5, 1.7, 3.6, 2.4, 2.9]}
frame = DataFrame(data)

df = DataFrame(data, columns=['year', 'state', 'pop', 'debt'],index=['one', 'two', 'three', 'four', 'five'])
df['state']

df.ix['four']

df['debt'] = 16.5
df

df['xxx'] = df['debt']+df['pop']
df['xxx']

df['eastern'] = df['state']=='Ohio'
df.columns

pop = {'Nevada': {2001: 2.4, 2002: 2.9},'Ohio': {2000: 1.5, 2001: 1.7, 2002: 3.6}}
frame3 = DataFrame(pop)

frame3

frame3.T

frame3.index.name = 'year'; frame3.columns.name = 'state'
frame3.values

x = pd.read_clipboard
x.__sizeof__()

from lxml.html import parse
from urllib import request
parsed = parse(request.urlopen('http://finance.yahoo.com/q/op?s=AAPL+Options'))
doc = parsed.getroot()
links = doc.findall('.//a')

for i in range(10):
    print(i)
else:
    print("GO　TO　ＥＬＳＥ")
    for j in range(11, 20):
        print(j)


import csv
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
from mpl_toolkits.mplot3d import Axes3D
import time
import sys
import warnings

if not sys.warnoptions:
    warnings.simplefilter("ignore")

path_X = sys.argv[1];
path_Y = sys.argv[2];
learning_rate = float(sys.argv[3]);
time_gap = float(sys.argv[4]);
# Read the CSV files to create X_linear and Y_linear

read_1 = [];
with open(path_X) as csvfile:
    reader = csv.reader(csvfile, quoting=csv.QUOTE_NONNUMERIC) # change contents to floats
    for row in reader: # each row is a list
        read_1.append(row)

X_rawest = np.asarray(read_1)
mu = np.mean(X_rawest);
sigma = np.std(X_rawest);
X_raw = (X_rawest - mu)/sigma;
X_linear = np.c_[ np.ones((X_raw.shape[0],1)), X_raw]

read_2 = [];
with open(path_Y) as csvfile:
    reader = csv.reader(csvfile, quoting=csv.QUOTE_NONNUMERIC) # change contents to floats
    for row in reader: # each row is a list
        read_2.append(row)

Y_linear = np.asarray(read_2)

m = Y_linear.shape[0];
#Function to compute cost

def compute_cost(X,Y,theta):
    h = np.matmul(X,theta);
    J = np.sum(np.square(h-Y))/(2*m);
    return float(J);

#Function for Gradient Descent

def grad_descent(X,Y,theta,alpha):
    h = np.matmul(X,theta);
    d_theta = np.zeros(theta.shape);
    d_theta[0] = np.matmul((h-Y).T,X[:,0])/m;
    d_theta[1] = np.matmul((h-Y).T,X[:,1])/m;
    theta = theta - alpha * d_theta;
    return theta;

#Function to do the regression

def linear_reg(X,Y,theta,alpha, max_iter):
    J = [];
    theta0_iter = [];
    theta1_iter = [];
    J.append(compute_cost(X,Y,theta));
    theta0_iter.append(theta[0]);
    theta1_iter.append(theta[1]);
    for i in range (max_iter):
        theta = grad_descent(X,Y,theta,alpha);
        J.append(compute_cost(X,Y,theta));
        theta0_iter.append(theta[0]);
        theta1_iter.append(theta[1]);
        delta = np.abs(J[i+1] - J[i])/alpha;
        if(delta<np.power(10.0,-10)):
            #print("Number of iterations ", i);
            #print("Final cost ", J[i]);
            break;
    return theta,J, theta0_iter, theta1_iter;

def plot_contour(X,Y,eta,time_gap):
  fig, ax = plt.subplots()
  plt.figure(fig.number)
  X_3d = np.arange(-1, 3, 0.05)
  Y_3d = np.arange(-1, 1, 0.05)

  Z_3d = np.zeros((X_3d.shape[0],Y_3d.shape[0]))
  for i in range(X_3d.shape[0]):
      for j in range(Y_3d.shape[0]):
          Z_3d[i,j] = compute_cost(X_linear, Y_linear,np.array([X_3d[i], Y_3d[j]]))/m;
  X_3d, Y_3d = np.meshgrid(X_3d, Y_3d)

  plt.contour(X_3d,Y_3d,Z_3d.T,10);
  plt.title('Learning Rate = %.2f' %eta);
  theta = np.zeros((2,1));
  [theta,J, t0_iter, t1_iter] = linear_reg(X_linear,Y_linear,theta,eta, max_iter);
  rounder = 1;
  for i in range(round(len(J)/rounder)):
    x0 = t0_iter[i*rounder];
    x1 = t1_iter[i*rounder];
    if(x0*x0 + x1*x1 > 100):
      break;
    scat = ax.scatter(x0,x1,c='r');
    fig.canvas.draw();
    plt.pause(time_gap)
  return fig;

theta = np.zeros((2,1));
alpha = learning_rate;
max_iter = np.power(10,3);
[theta,J, t0_iter, t1_iter] = linear_reg(X_linear,Y_linear,theta,alpha, max_iter);
t0_iter = np.array(t0_iter);
t1_iter = np.array(t1_iter);
theta_final = np.zeros((2,1));
theta_final[0] = theta[0]-mu*theta[1]/sigma;
theta_final[1] = theta[1]/sigma;
print("Theta 0 : ", theta_final[0,0]);
print("Theta 1 : ", theta_final[1,0]);
input("Press Enter to go to part (b)")
fig,ax = plt.subplots()
plt.plot(X_rawest,Y_linear,'ro');
x1 = np.arange(np.min(X_rawest)-5, np.max(X_rawest)+5, 0.01)
y1 = theta_final[0] + theta_final[1]*x1;
plt.plot(x1,y1,'k',linewidth=2.0,);
plt.xlabel('Inputs')
plt.ylabel('Outputs')
plt.title('Linear Regression')
plt.show(block=False);
input("Press Enter to go to part (c)")
plt.close(fig)
plt.ion();
fig1 = plt.figure(1)
ax1 = fig1.add_subplot(111, projection='3d')

X_3d = np.arange(0, 2, 0.05)
Y_3d = np.arange(-1, 1, 0.05)
Z_3d = np.zeros((X_3d.shape[0],Y_3d.shape[0]))
for i in range(X_3d.shape[0]):
    for j in range(Y_3d.shape[0]):
        Z_3d[i,j] = compute_cost(X_linear, Y_linear,np.array([X_3d[i], Y_3d[j]]))/m;
X_3d, Y_3d = np.meshgrid(X_3d, Y_3d)

ax1.plot_surface(X_3d, Y_3d, Z_3d, cmap='magma',alpha=0.7)
plt.title('3D Plot for Error Function vs Theta');
ax1.view_init(elev=45,azim=20);
J_array=[]
rounder=1;
for i in range(round(len(J)/rounder)):
  x0 = t0_iter[i*rounder,0];
  x1 = t1_iter[i*rounder,0];
  J_cost = J[i*rounder];
  ax1.scatter(xs=x0,ys=x1,zs=J_cost,c='r');
  fig1.canvas.draw();
  plt.pause(time_gap);
input("Press Enter to go to part (d)")
plt.close(fig1);
plt.ioff()
figx = plot_contour(X_linear,Y_linear,alpha,time_gap);
input("Press Enter to go to part (e)")
plt.close(figx);
eta_array = [0.1, 0.5, 0.9, 1.3, 1.7, 2.1, 2.5];
for eta in eta_array:
  figy = plot_contour(X_linear,Y_linear,eta,time_gap);
  time.sleep(2);
  plt.close(figy);


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

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

p_a = len(df[df['fico']>700])/len(df)
print("Probability of event that fico credit score is greater than 700 : ",p_a)

p_b = len(df[df['purpose']=='debt_consolidation'])/len(df)
print("Probability of event that purpose == 'debt_consolation' : ",p_b)

df1 = df[df['purpose']=='debt_consolidation']
p_a_b = len(df1[df1['purpose']=='debt_consolidation'])/len(df1[df1['fico']>700])
print("Probability of event for the event purpose == 'debt_consolidation' given 'fico' credit score is greater than 700 : ",p_a_b)

result = p_a_b==p_a
print(result)

# code ends here

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

prob_lp = len(df[df['paid.back.loan']=='Yes'])/len(df)
print(prob_lp)

prob_cs = len(df[df['credit.policy']=='Yes'])/len(df)
print(prob_cs)

new_df = df[df['paid.back.loan']=='Yes']

prob_pd_cs = len(new_df[new_df['credit.policy']=='Yes'])/len(new_df[new_df['paid.back.loan']=='Yes'])
print(prob_pd_cs)

bayes = (prob_pd_cs*prob_lp)/prob_cs
print(bayes)

# code ends here

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

df['purpose'].value_counts(normalize=True).plot(kind='bar')
plt.title("Probability Distribution of Purpose")
plt.ylabel("Probability")
plt.xlabel("Number of Purpose")
plt.show()

df1 = df[df['paid.back.loan']=='No']

df1['purpose'].value_counts(normalize=True).plot(kind='bar')
plt.title("Probability Distribution of Purpose")
plt.ylabel("Probability")
plt.xlabel("Number of Purpose")
plt.show()

# code ends here

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

inst_median = np.median(df['installment'])

inst_mean = np.mean(df['installment'])

df['installment'].plot(kind='hist', bins=50)
plt.axvline(x=inst_median,color='r')
plt.axvline(x=inst_mean,color='g')
plt.show()

df['log.annual.inc'].plot(kind='hist', bins=50)
plt.show()

# code ends here


"""
Objetivo: Resolver questão 2, as primeiras duas matirzes primeiro laboratorio.
"""
import numpy as np
from scipy.linalg import toeplitz

a = np.eye(5)       #gera uma matriz identidade do tamanho do parametro
#print(f'Matriz a = \n{a}')
b = np.array([[2, 0, 0, 0, 0],
              [2, 2, 0, 0, 0],
              [2, 2, 2, 0, 0],
              [2, 2, 2, 2, 0],
              [2, 2, 2, 2, 2]])
#print(f'Matriz b = \n{b}')
c = np.diag(np.diag(b))     #extrai a diagonal em questãodiag(matiz, k)
#print(c)
d = np.diagflat([[1, 2], [3, 4]], 1)        #escreve uma matriz onde geral é zero menos a diagonal
                                            # definida nos parametros, q tem q ser escrita de 2 em 2
#print(d)
e = toeplitz([1, 1, 0, 3], [0, 2, 0, 2])    #Escreve uma matriz([d, d-1, d-2, ...], [d(n), d+1, d+2, ...])
#print(e)
b_2 = toeplitz([2, 2, 2, 2, 2], [0, 0, 0, 0, 0])
#print(b_2)
f = np.arange(10, 2, -1)        #gera matriz (começo, fim, passo) mas so uma dimensao
f = f.reshape(2, 4)             #redefine o numero de dimensoes(linha, coluna),se falta ou sobre termo ela n roda
print(f)


import numpy as np
import matplotlib.pyplot as plt

def FE_logistic(u0, dt, N):
    u = np.zeros(N+1)
    u[0] = u0
    for n in range(N):
        u[n+1] = u[n] + dt*(u[n] - u[n]**2)
    return u

def quadratic_roots(a, b, c):
    delta = b**2 - 4*a*c
    r2 = (-b + np.sqrt(delta))/float(2*a)
    r1 = (-b - np.sqrt(delta))/float(2*a)
    return r1, r2

def BE_logistic(u0, dt, Nt, choice='Picard',
                eps_r=1E-3, omega=1, max_iter=1000):
    if choice == 'Picard1':
        choice = 'Picard'
        max_iter = 1

    u = np.zeros(Nt+1)
    iterations = []
    u[0] = u0
    for n in range(1, Nt+1):
        a = dt
        b = 1 - dt
        c = -u[n-1]
        if choice in ('r1', 'r2'):
            r1, r2 = quadratic_roots(a, b, c)
            u[n] = r1 if choice == 'r1' else r2
            iterations.append(0)

        elif choice == 'Picard':
            def F(u):
                return a*u**2 + b*u + c

            u_ = u[n-1]
            k = 0
            while abs(F(u_)) > eps_r and k < max_iter:
                u_ = omega*(-c/(a*u_ + b)) + (1-omega)*u_
                k += 1
            u[n] = u_
            iterations.append(k)

        elif choice == 'Newton':
            def F(u):
                return a*u**2 + b*u + c

            def dF(u):
                return 2*a*u + b

            u_ = u[n-1]
            k = 0
            while abs(F(u_)) > eps_r and k < max_iter:
                u_ = u_ - F(u_)/dF(u_)
                k += 1
            u[n] = u_
            iterations.append(k)
    return u, iterations

def CN_logistic(u0, dt, Nt):
    u = np.zeros(Nt+1)
    u[0] = u0
    for n in range(0, Nt):
        u[n+1] = (1 + 0.5*dt)/(1 + dt*u[n] - 0.5*dt)*u[n]
    return u

def quadratic_root_goes_to_infinity():
    """
    Verify that one of the roots in the quadratic equation
    goes to infinity.
    """
    for dt in 1E-7, 1E-12, 1E-16:
        a = dt
        b = 1 - dt
        c = -0.1
        print((dt, quadratic_roots(a, b, c)))

print('sympy calculations')
import sympy as sym
dt, u_1, u = sym.symbols('dt u_1 u')
r1, r2 = sym.solve(dt*u**2 + (1-dt)*u - u_1, u)
print(r1)
print(r2)
print((r1.series(dt, 0, 2)))
print((r2.series(dt, 0, 2)))

T = 9
try:
    dt = float(sys.argv[1])
    eps_r = float(sys.argv[2])
    omega = float(sys.argv[3])
except:
    dt = 0.8
    eps_r = 1E-3
    omega = 1
N = int(round(T/float(dt)))

u_BE3, iter_BE3 = BE_logistic(0.1, dt, N, 'Picard', eps_r, omega)
print(iter_BE3)
print(('Picard mean no of iterations (dt=%g):' % dt, int(round(np.mean(iter_BE3)))))

u_FE = FE_logistic(0.1, dt, N)
u_BE1, _ = BE_logistic(0.1, dt, N, 'r1')
u_BE2, _ = BE_logistic(0.1, dt, N, 'r2')
u_BE31, iter_BE31 = BE_logistic(0.1, dt, N, 'Picard1', eps_r, omega)
u_BE3, iter_BE3 = BE_logistic(0.1, dt, N, 'Picard', eps_r, omega)
u_BE4, iter_BE4 = BE_logistic(0.1, dt, N, 'Newton', eps_r, omega)
u_CN = CN_logistic(0.1, dt, N)

from numpy import mean
print(('Picard mean no of iterations (dt=%g):' % dt, int(round(np.mean(iter_BE3)))))
print(('Newton mean no of iterations (dt=%g):' % dt, int(round(np.mean(iter_BE4)))))

t = np.linspace(0, dt*N, N+1)
plt.plot(t, u_FE, t, u_BE2, t, u_BE3, t, u_BE31, t, u_BE4, t, u_CN)
plt.legend(['FE', 'BE exact', 'BE Picard', 'BE Picard1', 'BE Newton', 'CN gm'])
plt.title('dt=%g, eps=%.0E' % (dt, eps_r))
plt.xlabel('t')
plt.ylabel('u',)
filestem = 'logistic_N%d_eps%03d' % (N, np.log10(eps_r))
plt.savefig(filestem + '_u.png')
plt.savefig(filestem + '_u.pdf')
plt.figure()
plt.plot(list(range(1, len(iter_BE3)+1)), iter_BE3, 'r-o',
         list(range(1, len(iter_BE4)+1)), iter_BE4, 'b-o')
plt.legend(['Picard', 'Newton'])
plt.title('dt=%g, eps=%.0E' % (dt, eps_r))
plt.axis([1, N+1, 0, max(iter_BE3 + iter_BE4)+1])
plt.xlabel('Time level')
plt.ylabel('No of iterations')
plt.savefig(filestem + '_iter.png')
plt.savefig(filestem + '_iter.pdf')


# https://ml-cheatsheet.readthedocs.io/en/latest/loss_functions.html
from tensor import Tensor
import numpy as np
from math import *

# Loss functions

def cross_entropy(y_pred, y_true):
  return -sum([y_true[i]*log2(y_pred[i]) for i in range(len(y_pred))])

def binary_classification(y_pred, y_true):
  return -(y_true * log(y_pred) + (1 - y_true) * log(1 - y_pred))

# ----

if __name__ == "__main__":
  predictions = np.array([[0.25,0.25,0.25,0.25],
                          [0.01,0.01,0.01,0.96]])
  targets = np.array([[0,0,0,1], [0,0,0,1]])
  ans = 0.71355817782  #Correct answer
  x = cross_entropy(predictions, targets)
  print(np.isclose(x,ans))

  p = [0.10, 0.40, 0.50]
  q = [0.80, 0.15, 0.05]

  print(cross_entropy(q, p))


import numpy as np
from scipy.special import softmax
import seaborn as sns
import matplotlib.pyplot as plt

if __name__ == '__main__':
    data_size = 100
    true_grad = 3
    true_intercept = 1
    true_sig = 1

    x = np.linspace(0, 10, data_size)
    # y = m x + c
    y_obs = true_grad * x + true_intercept + np.random.normal(loc=0, scale=true_sig, size=data_size)

    M = 2000000
    m = M // 20  # M/m is usually around 20
    print(f'Generating {M} initial samples, and {m} re-samples')

    # sample M params from initial prior
    grad_prior = np.random.uniform(-10, 10, M)  # m ~ U(-10, 10)
    intercept_prior = np.random.uniform(-10, 10, M)  # c ~ U(-10, 10)
    sig_prior = np.random.uniform(0.1, 20, M)  # sig ~ U(0.1, 10)

    # calculate importance weights, assuming that we model y ~ N(mu, sig)
    exponent = 1 / (2 * sig_prior ** 2) \
               * np.sum([(y_obs[i] - (grad_prior * x[i] + intercept_prior)) ** 2 for i in range(data_size)], axis=0)

    log_weights = - data_size * np.log(sig_prior * np.sqrt(2 * np.pi)) - exponent

    weights = softmax(log_weights)

    # resample params using the above weights to get posterior
    grad_posterior = np.random.choice(grad_prior, m, p=weights)
    intercept_posterior = np.random.choice(intercept_prior, m, p=weights)
    sig_posterior = np.random.choice(sig_prior, m, p=weights)

    # report summary stats
    print(f'True gradient: {true_grad}')
    print(f'True intercept: {true_intercept}')
    print(f'True sigma: {true_sig}')
    print(f'Gradient posterior: mean={np.mean(grad_posterior):.3} - sd={np.std(grad_posterior):.3}')
    print(f'Intercept posterior: mean={np.mean(intercept_posterior):.3} - sd={np.std(intercept_posterior):.3}')
    print(f'Sigma posterior: mean={np.mean(sig_posterior):.3} - sd={np.std(sig_posterior):.3}')

    # plot the new samples
    fig, axes = plt.subplots(1, 4, figsize=(12, 3))

    axes[0].set_title('Data')
    axes[1].set_title('Gradient Posterior')
    axes[2].set_title('Intercept Posterior')
    axes[3].set_title('Sigma Posterior')

    axes[0].plot(x, y_obs, 'x')
    sns.distplot(grad_posterior, ax=axes[1])
    sns.distplot(intercept_posterior, ax=axes[2])
    sns.distplot(sig_posterior, ax=axes[3])
    plt.show()

    fig, ax = plt.subplots(figsize=(5, 5))
    ax.set_xlabel('Gradient')
    ax.set_ylabel('Intercept')
    ax.set_title('Joint distribution p(m, c)')
    sns.kdeplot(grad_posterior, intercept_posterior, shade=True, ax=ax)
    plt.show()


import numpy as np
import networkx as nx
from sklearn.cluster import SpectralClustering
from sklearn import metrics
np.random.seed(1)

# Get your mentioned graph
G = nx.karate_club_graph()

# Get ground-truth: club-labels -> transform to 0/1 np-array
#     (possible overcomplicated networkx usage here)
gt_dict = nx.get_node_attributes(G, 'club')
gt = [gt_dict[i] for i in G.nodes()]
gt = np.array([0 if i == 'Mr. Hi' else 1 for i in gt])

# Get adjacency-matrix as numpy-array
adj_mat = nx.to_numpy_matrix(G)

print('ground truth')
print(gt)

# Cluster
sc = SpectralClustering(2, affinity='precomputed', n_init=100)
sc.fit(adj_mat)

# Compare ground-truth and clustering-results
print('spectral clustering')
print(sc.labels_)
print('just for better-visualization: invert clusters (permutation)')
print(np.abs(sc.labels_ - 1))

# Calculate some clustering metrics
print(metrics.adjusted_rand_score(gt, sc.labels_))
print(metrics.adjusted_mutual_info_score(gt, sc.labels_))


from scipy.optimize import curve_fit
import numpy as np

def uptake_func(po2, a, b, c):
    return a - ((b * po2) / (c + po2))

def fit():
    uptake = [10.91, 10.9, 7.7, 5.6, 1.0, 0.628, 0.5]
    po2 = [0.0, 0.0076, 0.76, 3.8, 38, 60, 152]
    #po2 = [0.0, 0.76, 3.8, 38, 152]

    pars, cov = curve_fit(f=uptake_func, xdata=po2, ydata=uptake,
                          p0=[10.9, 10.7, 2.5])
                          # sigma=[1, 1, 10, 10, 10, 10, 1])

    stdevs = np.sqrt(np.diag(cov))  # Calculate the residuals
    # res = y_dummy - power_law(x_dummy, *pars)
    print(pars)
    print(cov)

if __name__ == "__main__":
    # execute only if run as a script
    fit()


from inspect import signature
import numpy as np
import logging
from mpl_toolkits import mplot3d

def df_dx(func, epsilon=1e-3):
	nargs = len(signature(func).parameters)
	# 3D function
	if nargs == 2:
		return lambda x, y: ((func(x + epsilon, y) - func(x, y)) / epsilon)
	# 2D function
	if nargs == 1:
		return lambda x: ((func(x + epsilon) - func(x)) / epsilon)
	logging.error('Cannot work on functions with more than 2 variables')

def df_dy(func, epsilon=1e-3):
	return lambda x, y: ((func(x, y + epsilon) - func(x, y)) / epsilon)

def df_dxdx(func):
	nargs = len(signature(func).parameters)
	# 3D function
	if nargs == 2:
		return lambda x, y: df_dx(df_dx(func))(x, y)
	# 2D function
	if nargs == 1:
		return lambda x: df_dx(df_dx(func))(x)
	logging.error('Cannot work on functions with more than 2 variables')

def df_dydy(func):
	return lambda x, y: df_dy(df_dy(func))(x, y)

def df_dxdy(func):
	return lambda x, y: df_dx(df_dy(func))(x, y)

def df_dydx(func):
	return lambda x, y: df_dy(df_dx(func))(x, y)

def grad(func):
	nargs = len(signature(func).parameters)
	if nargs == 2:
		return lambda x, y: np.array([df_dx(func)(x, y), df_dy(func)(x, y)])
	logging.error('Cannot calculate gradient, function is not 3D')

def hess(func):
	nargs = len(signature(func).parameters)
	if nargs == 2:
		return lambda x, y: np.array([[df_dxdx(func)(x, y), df_dxdy(func)(x, y)],
		                              [df_dydx(func)(x, y), df_dydy(func)(x, y)]])
	logging.error('Cannot calculate hessian, function is not 3D')

def newton(func, x0=(0, 0), steps=2, delta=.05):
	nargs = len(signature(func).parameters)

	# 3D function
	if nargs == 2:
		res = np.array([x0[0], x0[1]])
		gradient = grad(func)
		hessian = hess(func)

		for i in range(steps):
			gd = gradient(res[0], res[1])
			hs = hessian(res[0], res[1])
			inverse = np.linalg.inv(hs)
			prev = res
			res = prev - (np.dot(gd, inverse))
			diff = abs(func(res[0], res[1]) - func(prev[0], prev[1]))
			if diff < delta:
				break

	# 2D function
	elif nargs == 1:
		res = x0
		dx = df_dx(func)
		dxdx = df_dxdx(func)

		for i in range(steps):
			prev = res
			res = prev - dx(prev) / dxdx(prev)
			diff = abs(prev - res)
			if diff < delta:
				break

	return res

def plot(func, start=-10, end=10, bins=100, savefig=False, plotfunc=True, plotgrad=True, filename=''):
	from matplotlib import pyplot as plt
	nargs = len(signature(func).parameters)
	x = np.linspace(start, end, bins)

	# if given function is 2D
	if nargs == 1:
		X = np.linspace(start, end, bins)
		Y = func(X)
		dx = df_dx(func)(X)
		dxdx = df_dxdx(func)(X)

		fig = plt.figure(figsize=(8, 6))
		ax = fig.add_subplot(2, 2, 1, title='f(x)')
		ax.set_xlabel('x')
		ax.set_ylabel('y')
		ax.plot(Y)
		b = fig.add_subplot(2, 2, 2, title='f\'(x)')
		b.set_xlabel('x')
		b.set_ylabel('y')
		b.plot(dx)
		c = fig.add_subplot(2, 2, 3, title='f\'\'(x)')
		c.set_xlabel('x')
		c.set_ylabel('y')
		c.plot(dxdx)

	# 3D function
	elif nargs == 2:
		y = np.linspace(start, end, bins)

		X, Y = np.meshgrid(x, y)
		gradient = grad(func)
		gd = gradient(X, Y)
		Z = func(X, Y)

		fig = plt.figure(figsize=(8, 6))
		if plotfunc and plotgrad:
			ax = fig.add_subplot(1, 2, 1, projection='3d', title='f(x,y)', adjustable='box', aspect=1)
			ax.contour3D(X, Y, Z, 50, cmap='binary')
			ax.set_xlabel('x')
			ax.set_ylabel('y')
			ax.set_zlabel('z')
			b = fig.add_subplot(1, 2, 2, title='gradient', adjustable='box', aspect=1)
			b.quiver(X, Y, gd[0], gd[1])

		elif plotfunc:
			ax = fig.add_subplot(1, 1, 1, projection='3d', title='f(x,y)', adjustable='box', aspect=1)
			ax.contour3D(X, Y, Z, 50, cmap='binary')
			ax.set_xlabel('x')
			ax.set_ylabel('y')
			ax.set_zlabel('z')

		elif plotgrad:
			b = fig.add_subplot(1, 1, 1, title='gradient', adjustable='box', aspect=1)
			b.quiver(X, Y, gd[0], gd[1])

	plt.show()

	if savefig and plotfunc or plotgrad:
		if plotfunc and plotgrad:
			filename = 'plot'
		elif plotfunc:
			filename = 'function'
		elif plotgrad:
			filename = 'gradient'

		logging.info('saving plot as svg...')
		fig.savefig(filename + '.svg')

if __name__ == '__main__':
	np.set_printoptions(precision=3)
	print(newton(lambda x, y: 2 * (x ** 2) + (x * y) + 2 * ((y - 3) ** 2), (-1, 4)))
	plot(lambda x, y: 2 * (x ** 2) + (x * y) + 2 * ((y - 3) ** 2), plotfunc=False)
	plot(lambda x, y: 2 * (x ** 2) + (x * y) + 2 * ((y - 3) ** 2), plotgrad=False)
	print('%.2f' % newton(lambda x: x ** 2, 2))
	plot(lambda x: x ** 2)


from sympy import cancel, expand, gcd_list, symbols
from homogeneous import *

def circle(P1, P2, P3):
    # return (a, d, e, f) such that a*x**2 + a*y**2 + d*x*z + e*y*z + f*z**2 = 0 is the circle's equation
    x, y, z = symbols('x, y, z')
    x1, y1, z1, x2, y2, z2, x3, y3, z3 = P1[0], P1[1], P1[2], P2[0], P2[1], P2[2], P3[0], P3[1], P3[2]
    # generated by homogeneous-circle.py
    a = expand(x1*y2*z1*z2*z3**2 - x1*y3*z1*z2**2*z3 - x2*y1*z1*z2*z3**2 + x2*y3*z1**2*z2*z3 + x3*y1*z1*z2**2*z3 - x3*y2*z1**2*z2*z3)
    d = expand(-x1**2*y2*z2*z3**2 + x1**2*y3*z2**2*z3 + x2**2*y1*z1*z3**2 - x2**2*y3*z1**2*z3 - x3**2*y1*z1*z2**2 + x3**2*y2*z1**2*z2 - y1**2*y2*z2*z3**2 + y1**2*y3*z2**2*z3 + y1*y2**2*z1*z3**2 - y1*y3**2*z1*z2**2 - y2**2*y3*z1**2*z3 + y2*y3**2*z1**2*z2)
    e = expand(x1**2*x2*z2*z3**2 - x1**2*x3*z2**2*z3 - x1*x2**2*z1*z3**2 + x1*x3**2*z1*z2**2 - x1*y2**2*z1*z3**2 + x1*y3**2*z1*z2**2 + x2**2*x3*z1**2*z3 - x2*x3**2*z1**2*z2 + x2*y1**2*z2*z3**2 - x2*y3**2*z1**2*z2 - x3*y1**2*z2**2*z3 + x3*y2**2*z1**2*z3)
    f = expand(-x1**2*x2*y3*z2*z3 + x1**2*x3*y2*z2*z3 + x1*x2**2*y3*z1*z3 - x1*x3**2*y2*z1*z2 + x1*y2**2*y3*z1*z3 - x1*y2*y3**2*z1*z2 - x2**2*x3*y1*z1*z3 + x2*x3**2*y1*z1*z2 - x2*y1**2*y3*z2*z3 + x2*y1*y3**2*z1*z2 + x3*y1**2*y2*z2*z3 - x3*y1*y2**2*z1*z3)
    gcd = gcd_list([a, d, e, f])
    return cancel(a/gcd), cancel(d/gcd), cancel(e/gcd), cancel(f/gcd)

def on_circle(C, P):
    a, d, e, f, x, y, z = C[0], C[1], C[2], C[3], P[0], P[1], P[2]
    return expand(a*(x**2 + y**2) + d*x*z + e*y*z + f*z**2) == 0

def perpendicular(A, B, P):
    # return (u, v, w) such that u*x + v*y + w*z = 0 is perpendicular to AB and passes through P
    x1, y1, z1, x2, y2, z2, x3, y3, z3 = A[0], A[1], A[2], B[0], B[1], B[2], P[0], P[1], P[2]
    u, v = x1*z2 - x2*z1, y1*z2 - y2*z1
    return reduced(u*z3, v*z3, -u*x3 - v*y3)

def intersect(C1, C2, P1):
    # return another intersection P2 of circles C1 and C2
    assert on_circle(C1, P1) and on_circle(C2, P1)
    CC1, CC2 = reduced(-C1[1], -C1[2], 2*C1[0]), reduced(-C2[1], -C2[2], 2*C2[0])
    C1C2, P1P2 = cross(CC1, CC2), perpendicular(CC1, CC2, P1)
    M = cross(C1C2, P1P2)
    x1, y1, z1, x2, y2, z2 = P1[0], P1[1], P1[2], M[0], M[1], M[2]
    P2 = reduced(2*x2*z1 - x1*z2, 2*y2*z1 - y1*z2, z1*z2)
    assert on_circle(C1, P2) and on_circle(C2, P2)
    return P2

def circle_eq(C):
    return f'({C[0]})*x**2 + ({C[0]})*y**2 + ({C[1]})*x*z + ({C[2]})*y*z + ({C[3]})*z**2 = 0'

def main():
    # https://en.wikipedia.org/wiki/Five_circles_theorem
    a, b, c, d, e, f, g = symbols('a, b, c, d, e, f, g')
    A0A1, A1A2, A2A3, A3A4, A4A0 = (1, 0, 0), (a, 1, 0), (b, c, 1), (d, e, 1), (f, g, 1)
    A0, A1, A2, A3, A4 = cross(A4A0, A0A1), cross(A0A1, A1A2), cross(A1A2, A2A3), cross(A2A3, A3A4), cross(A3A4, A4A0)
    B0, B1, B2, B3, B4 = cross(A1A2, A3A4), cross(A2A3, A4A0), cross(A3A4, A0A1), cross(A4A0, A1A2), cross(A0A1, A2A3)
    A2B0A3, A3B1A4, A4B2A0, A0B3A1, A1B4A2 = circle(A2, B0, A3), circle(A3, B1, A4), circle(A4, B2, A0), circle(A0, B3, A1), circle(A1, B4, A2)
    print('A2B0A3:', circle_eq(A2B0A3))
    print('A3B1A4:', circle_eq(A3B1A4))
    print('A4B2A0:', circle_eq(A4B2A0))
    print('A0B3A1:', circle_eq(A0B3A1))
    print('A1B4A2:', circle_eq(A1B4A2))
    C4 = intersect(A3B1A4, A4B2A0, A4)
    print('C4:', C4, flush = True)
    C0 = intersect(A4B2A0, A0B3A1, A0)
    print('C0:', C0, flush = True)
    C1 = intersect(A0B3A1, A1B4A2, A1)
    print('C1:', C1, flush = True)
    C2 = intersect(A1B4A2, A2B0A3, A2)
    print('C2:', C2, flush = True)
    # C0C1C2 = circle(C0, C1, C2)
    # print('C0C1C2:', circle_eq(C0C1C2), flush = True)
    # print('Is C4 on C0C1C2?', on_circle(C0C1C2, C4), flush = True)

if __name__ == '__main__':
    main()


from functools import reduce
import numpy as np

from src.kmeans.point import Point
from src.kmeans.cluster import Cluster

def center(points: [Point]) -> Point:
    return reduce(lambda x, y: x + y, points) / len(points)

def random_init(points: [Point], k: int) -> [Cluster]:
    points_coords = np.array(list(map(lambda p: p.coordinates, points)))
    unique_points = np.unique(points_coords, axis=0)
    random_points = unique_points[np.random.choice(len(unique_points), size=k, replace=False)]
    return list(map(lambda p: Cluster(Point(p)), random_points))

def euclidean(a: np.ndarray, b: np.ndarray) -> np.ndarray:
    return np.linalg.norm(a[:, np.newaxis] - b, axis=2)

def group_by_values(values):
    indices = np.arange(len(values))
    values_with_idx = np.array([values, indices]).T
    values_sorted = values_with_idx[values_with_idx[:, 0].argsort()]
    return np.split(values_sorted[:, 1], np.unique(values_sorted[:, 0], return_index=True)[1][1:])

def assign_nearest(points: [Point], clusters: [Cluster]):
    points_coords = np.array(list(map(lambda p: p.coordinates, points)))
    clusters_coords = np.array(list(map(lambda c: c.center.coordinates, clusters)))
    distances = euclidean(points_coords, clusters_coords)
    assignments = np.argmin(distances, axis=1)
    points_idx_by_cluster = group_by_values(assignments)

    for i in range(len(clusters)):
        assigned_points = list(map(lambda idx: points[idx], points_idx_by_cluster[i]))
        clusters[i].points = assigned_points

def update_centers(clusters: [Cluster]) -> bool:
    changed = False
    for c in clusters:
        new_center = center(c.points)
        if new_center != c.center:
            c.center = new_center
            changed = True
    return changed

def run(points: [Point], k: int) -> [Cluster]:
    clusters = random_init(points, k)
    converged = False
    while not converged:
        assign_nearest(points, clusters)
        converged = not update_centers(clusters)
    return clusters


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

#read data
#feature data
dataX=np.genfromtxt("x.csv",delimiter=',')
#target data
dataT=np.genfromtxt("t.csv",delimiter=',')
dataT=dataT.reshape(len(dataT),1)

def normalization(X):
    M=3
    s=0.1
    x_1=(X-(2*0/M))/s
    x_2=(X-(2*1/M))/s
    x_3=(X-(2*2/M))/s
    return np.column_stack((x_1,x_2,x_3))

def sigmoidal(X):
    return 1/(1+np.exp(-1*X))

def bayesian_regression(X,T):
    beta=1
    S_0_inv=np.eye(3)*(10**-6)
    m_0=np.zeros((3,1))
    S_N_inv=S_0_inv+beta*(X.T@X)
    S_N=np.linalg.inv(S_N_inv)
    temp=(S_0_inv@m_0)
    m_N=(S_N@((S_0_inv@m_0)+beta*((X.T@T))))
    return m_N,S_N

N=80
dataX_nor=normalization(dataX[0:N])
dataX_s=sigmoidal(dataX_nor)
m_N,S_N=bayesian_regression(dataX_s,dataT[0:N])

#generate 5 sample curves
#the testing dataset need to pass same data preprocessing
x1=np.linspace(0,2,10000)
x1_nor=normalization(x1)
x1_s=sigmoidal(x1_nor)
weight=np.random.multivariate_normal(m_N.reshape(3,),S_N).reshape(3,1)
y1=x1_s@weight

x2=np.linspace(0,2,10000)
x2_nor=normalization(x2)
x2_s=sigmoidal(x2_nor)
weight=np.random.multivariate_normal(m_N.reshape(3,),S_N).reshape(3,1)
y2=x2_s@weight

x3=np.linspace(0,2,10000)
x3_nor=normalization(x3)
x3_s=sigmoidal(x3_nor)
weight=np.random.multivariate_normal(m_N.reshape(3,),S_N).reshape(3,1)
y3=x3_s@weight

x4=np.linspace(0,2,10000)
x4_nor=normalization(x4)
x4_s=sigmoidal(x4_nor)
weight=np.random.multivariate_normal(m_N.reshape(3,),S_N).reshape(3,1)
y4=x4_s@weight

x5=np.linspace(0,2,10000)
x5_nor=normalization(x5)
x5_s=sigmoidal(x5_nor)
weight=np.random.multivariate_normal(m_N.reshape(3,),S_N).reshape(3,1)
y5=x5_s@weight

#visualize
plt.plot(dataX[0:N],dataT[0:N],'bo',label='training data')
plt.plot(x1,y1,label='sample curve 1')
plt.plot(x2,y2,label='sample curve 2')
plt.plot(x3,y3,label='sample curve 3')
plt.plot(x4,y4,label='sample curve 4')
plt.plot(x5,y5,label='sample curve 5')
plt.xlabel('x')
plt.ylabel('t')
plt.title('training data size: %d'%(N))
plt.legend()
plt.show()

#mean and std calculation
sample_mean=[]
sample_std=[]
hbound=[]
lbound=[]
for i in range(len(y1)):
    sample_mean.append(np.mean([y1[i],y2[i],y3[i],y4[i],y5[i]]))
    sample_std.append(np.std([y1[i],y2[i],y3[i],y4[i],y5[i]]))
    hbound.append(sample_mean[i]+sample_std[i])
    lbound.append(sample_mean[i]-sample_std[i])

#visualize
plt.plot(dataX[0:N],dataT[0:N],'bo',label='training data')
plt.plot(x1,sample_mean,label='mean curve')
plt.fill_between(x1,sample_mean,hbound,facecolor='pink')
plt.fill_between(x1,sample_mean,lbound,facecolor='pink')
plt.xlabel('x')
plt.ylabel('t')
plt.title('training data size: %d'%(N))
plt.legend()
plt.show()

#sample weight calculation and scatter
weight0=[]
weight1=[]
weight2=[]
for i in range(10000):
    weight=np.random.multivariate_normal(m_N.reshape(3,),S_N).reshape(3,1)
    weight0.append(weight[0])
    weight1.append(weight[1])
    weight2.append(weight[2])
weight0 = np.array(weight0).reshape(10000,)
weight1 = np.array(weight1).reshape(10000,)
weight2 = np.array(weight2).reshape(10000,)
plt.hist2d(np.array(weight0),np.array(weight1),range=[[0,5],[-6,6]],bins = 50,cmap = 'rainbow')
plt.xlabel("w[0]")
plt.ylabel("w[1]")
plt.title('weight scatter with training data size: %d' %(N))
plt.colorbar()
plt.show()


import numpy as np
from scipy import stats
import matplotlib.pyplot as plt
plt.rcParams["figure.figsize"] = (15,4)

mu_true = np.array([0.5, 0.5])
sigma_true = 0.1*np.array([[2,1],[1,1]])
n_sample = 10
x_sample = stats.multivariate_normal.rvs(mu_true, sigma_true, n_sample)

# 绘制采样数据和真实数据
ax1 = plt.subplot(131)
ax1.plot(x_sample[:,0], x_sample[:,1], 'bo', markersize=8)
plt.title('data')
ax1.plot(mu_true[0], mu_true[1], marker='x', color='black', markersize=15)
ax1.set_xlim([-1,1])
ax1.set_ylim([-1,1])

# 绘制先验分布
ax2 = plt.subplot(132)
prior_mu = np.array([0,0])
prior_sigma = 0.1*np.eye(2)

xy_range = np.linspace(-1,1,100)
X,Y=np.meshgrid(xy_range, xy_range)
XY = np.dstack((X, Y)).reshape((-1, 2))
Z = stats.multivariate_normal.pdf(XY, prior_mu, prior_sigma).reshape(X.shape)
ax2.contour(X, Y, Z)
plt.title('prior')
ax2.set_xlim([-1,1])
ax2.set_ylim([-1,1])

# 更新协方差矩阵
s_0 = prior_sigma
s0_inv = np.linalg.inv(s_0)
s = sigma_true
s_inv = np.linalg.inv(s)
s_n = np.linalg.inv(s0_inv + n_sample*s_inv)

# 更新期望
mu_0 = prior_mu
x_bar = np.mean(x_sample, 0)[:, np.newaxis]
mu_n = np.dot(s_n, n_sample*s_inv.dot(x_bar) + s0_inv.dot(mu_0[:, np.newaxis]))

# 绘制后验分布
post_mu = mu_n.flatten()
post_sigma = s_n
ax3 = plt.subplot(133)
post_z = stats.multivariate_normal.pdf(XY, post_mu, post_sigma).reshape(X.shape)
ax3.contour(X, Y, post_z)
plt.title('post after 10 obs')
ax3.set_xlim([-1,1])
ax3.set_ylim([-1,1])

plt.show()


# (c) 2019 Francis Taylor
# This code is licensed under the MIT license (see LICENSE for details)
# This code is provided as a guide for learning. Please do not copy it blindly.

# m =  [N Σ(xy) − Σx Σy] / [N Σ(x2) − (Σx)2]
# b = [Σy − m Σx ]/ N
# D:\Coding\git\physics-projects\Projects\Least Sqaures\files\LinearTestData.txt

import numpy as np
from numpy import genfromtxt
import pylab as plt
import os

# todo add errors

file_path = input("Enter the path of your file: ")
file_path = file_path.replace('"', '')
if os.path.isfile(file_path):
    values = genfromtxt(file_path, delimiter='\t', dtype=None)
    # print(values)
    x_vals = values[:, 0]
    x_error = values[:, 2]
    y_vals = values[:, 1]
    y_error = values[:, 3]
    A = np.vstack([x_vals, np.ones(len(x_vals))]).T
    m, c = np.linalg.lstsq(A, y_vals, rcond=None)[0]
    print("y={}x + {}".format(m, c))
    plt.plot(x_vals, y_vals, 'o', label='Original data', markersize=3)
    plt.plot(x_vals, m*x_vals + c, 'r', label='Fitted line')
    plt.legend()
    plt.title("y={:f}x + {:f}".format(m, c))
    plt.show()
else:
    print("File does not exist at: {}".format(str(file_path)))


from __future__ import absolute_import, division, print_function
from functools import reduce
from concurrent import futures
import numpy as np
import scipy.signal as spsg
import rasterio
import click
import os

def horn_gradient(dem):
    x_kernel = np.array([
        [-1/8, 0, 1/8],
        [-1/4, 0, 1/4],
        [-1/8, 0, 1/8]])
    y_kernel = np.array([
        [-1/8, -1/4, -1/8],
        [0, 0, 0],
        [1/8, 1/4, 1/8]])
    dx = spsg.convolve2d(dem, x_kernel)
    dy = spsg.convolve2d(dem, y_kernel)
    return dx, dy

def slope(dem):
    dx, dy = horn_gradient(dem)
    dem_slope = np.arctan(np.sqrt(np.square(dx) + np.square(dy)))
    return dem_slope

def aspect(dem):
    dx, dy = horn_gradient(dem)
    direction = np.arctan2(dy, -dx)
    dem_aspect = np.where(direction > np.pi/2, np.pi*5/2 - direction, np.pi/2 - direction)
    return dem_aspect

def hillshade(dem, azimuth, altitude):
    azimuth_rad = np.deg2rad(azimuth)
    altitude_rad = np.deg2rad(altitude)
    dem_slope = slope(dem)
    dem_aspect = aspect(dem)
    dem_hillshade = 255 * (np.cos(np.pi/2 - altitude_rad) * np.cos(dem_slope) + np.sin(np.pi/2 - altitude_rad) * np.sin(dem_slope) * np.cos(azimuth_rad - dem_aspect))
    return dem_hillshade

def mdow_hillshade(dem, azimuth, altitude):
    azimuth_rad = np.deg2rad(azimuth)
    altitude_rad = np.deg2rad(altitude)
    init_slope = slope(dem)
    init_aspect = aspect(dem)
    init_hillshade = hillshade(dem, azimuth, altitude)
    secondary_azimuths = [np.deg2rad(180+90*(n+1)) for n in range(4)]
    workers = futures.ThreadPoolExecutor(max_workers=os.cpu_count())
    hs_task = lambda az: hillshade(dem, az, altitude)
    w_var_task = lambda az: (np.cos(init_aspect - az) + 1)
    weight_task = lambda w: (w / np.sqrt(2 * w_total))
    secondary_hillshades = list(workers.map(hs_task, secondary_azimuths))
    secondary_w_vars = list(workers.map(w_var_task, secondary_azimuths))
    w_total = reduce(lambda x, y: x + y, secondary_w_vars)
    secondary_weights = list(workers.map(weight_task, secondary_w_vars))
    md_hillshade = reduce(lambda x, y: x + y, [m * n for m, n in zip(secondary_hillshades, secondary_weights)])
    merge_weight = np.square(np.sin(np.sin(altitude_rad) * np.cos(init_slope) + np.sin(init_slope) * np.cos(altitude_rad) * np.cos(init_aspect - azimuth_rad)))
    hs_final = merge_weight * md_hillshade + (1 - merge_weight) * init_hillshade
    mdow = np.min(init_hillshade) + (hs_final - np.min(hs_final)) / (np.max(hs_final) - np.min(hs_final)) * (np.max(init_hillshade) - np.min(init_hillshade))
    return mdow

def read_dem(dem_file):
    src = rasterio.open(dem_file)
    band = src.read(1)
    meta = {
        'height': band.shape[0],
        'width': band.shape[1],
        'count': src.count,
        'dtype': band.dtype,
        'crs': src.crs,
        'transform': src.transform,
        'nodata': src.nodata
    }
    src.close()
    return band, meta

def write_hillshade(file_path, hs, metadata):
    with rasterio.open(file_path, 'w', driver='GTiff', height=metadata['height'], width=metadata['width'], count=metadata['count'], dtype=metadata['dtype'], crs=metadata['crs'], transform=metadata['transform'], nodata=metadata['nodata']) as dst:
        dst.write(hs.astype(metadata['dtype']), 1)

def run(in_path, out_path, azimuth, altitude):
    arr, meta = read_dem(in_path)
    md = mdow_hillshade(arr, azimuth, altitude)
    write_hillshade(out_path, md, meta)

def validate_azimuth(ctx, param, value):
    if 0 <= value <= 360:
        return value
    else:
        raise click.BadParameter('Azimuth should be between 0 and 360.')

def validate_altitude(ctx, param, value):
    if 0 <= value <= 90:
        return value
    else:
        raise click.BadParameter('Altitude should be between 0 and 90.')

@click.command()
@click.option('-i', '--in', 'in_path', help='Input DEM path.', required=True, type=str)
@click.option('-o', '--out', 'out_path', help='Output hillshade path.', required=True, type=str)
@click.option('--azimuth', 'azimuth', help='Hillshade azimuth in degree.', required=True, type=float, callback=validate_azimuth)
@click.option('--altitude', 'altitude', help='Hillshade altitude in degree.', required=True, type=float, callback=validate_altitude)
def cmd(in_path, out_path, azimuth, altitude):
    """MDOW Hillshade Generator."""
    run(in_path, out_path, azimuth, altitude)

if __name__ == '__main__':
    cmd()


import numpy as np

def sigmoid(x):
    """
    S(x) = 1 / ( 1 + e^(-x) )
    :param x: input
    :return: S(x)
    """
    return 1 / (1 + np.exp(-x))

def relu(x):
    """
    f(x) = max(0, x)
    :param x:
    :return:
    """
    return max(0, x)

def tanh(x):
    """
    tanh x = (sinh x)/(cosh x) = (e^x - e(-x)) / (e^x + e(-x))
    :param x:
    :return:
    """
    return (np.exp(x) - np.exp(-x)) / (np.exp(x) + np.exp(-x))

def softmax(inputs):
    """
    y_k = exp(x_k) / sum(exp(x_i))
    :param inputs:
    :return:
    """
    _max = np.max(inputs)
    _exp = np.exp(inputs - _max)  # avoid overflow
    _sum_exp = np.sum(_exp)
    return _exp / _sum_exp


# T-Test Assignment

import numpy as np

"""
1.Certain refined edible oil is packed in tins holding 16 kg each. The filling machine can maintain this but with a standard deviation of 0.5 kg. Samples of 25 are taken from the production line. If a sample means is (i)16.35kg (ii)15.8kg, Can we be 95 percent sure that the sample has come from a population of 16kg tins?
"""

print("Assignment 1")

from scipy.stats import t
print("\nTrial 1 with 16.35")
pMean=16
sMean=16.35
n=25
tstatistics=(sMean-pMean)/(0.5/np.sqrt(n))
print("T Statistics:",tstatistics)
tcritical_l=t.ppf(q=0.05/2,df=n-1)
tcritical_u=-tcritical_l

if tstatistics<tcritical_l or tstatistics>tcritical_u:
    print("Reject the Null Hypothesis")
else:
    print("Fail to reject the Null Hypothesis")

print("\nTrial 2 with 15.8")
pMean=16
sMean=15.8
n=25
tstatistics=(sMean-pMean)/(0.5/np.sqrt(n))
print("T Statistics:",tstatistics)
tcritical_l=t.ppf(q=0.05/2,df=n-1)
tcritical_u=-tcritical_l

if tstatistics<tcritical_l or tstatistics>tcritical_u:
    print("Reject the Null Hypothesis")
else:
    print("Fail to reject the Null Hypothesis")

print("\n")

"""
2.A filling machine is expected to fill 5kg of powder into bags. A sample of 10 bags gave the weighs 4.7, 4.9, 5.0, 5.1, 5.4, 5.2, 4.6,5.1, 4.6 and 4.7. Test whether the machine is working properly.
"""
print("Assignment 2")
from scipy.stats import ttest_1samp
sample_array=np.array([4.7, 4.9, 5.0, 5.1, 5.4, 5.2, 4.6,5.1, 4.6, 4.7])
tstats,pvalue=ttest_1samp(sample_array,5)

print("T-statistics:",tstats)
print("P value:",pvalue)

if pvalue < 0.05:
    print("Reject the Null Hypothesis")
    print("The filling machine is working properly")
else:
    print("Fails to reject the Null Hypothesis")
    print("The filling machine is working properly")
print("\n")

"""
3.Two sets of ten students selected at random from a college were taken; One set was given memory test as they were and the other was given the memory test after two weeks of training and the scores are given below
Set A: 10 8 7 9 8 10 9 6 7 8
Set B: 12 8 8 10 8 11 9 8 9 9
Do you think there is a significant effect due to training?
"""
print("Assignement 3")

sample1=np.array([10,8,7,9,8,10,9,6,7,8])
sample2=np.array([12,8,8,10,8,11,9,8,9,9])

from scipy.stats import ttest_ind

tstats,pvalue=ttest_ind(sample1,sample2)

print("T-statistics:",tstats)
print("P value:",pvalue)

if pvalue < 0.05:
    print("Reject the Null Hypothesis")
    print("No significant effect due to Training")
else:
    print("Fails to reject the Null Hypothesis")
    print("Significant effect due to Training")


##%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
##                          PCA model for TE data
## %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

#%% import required packages
import numpy as np
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt

#%% fetch TE data
TEdata_noFault_train = np.loadtxt('d00.dat').T

# select data as done in Lee et al.
xmeas = TEdata_noFault_train[:,0:22]
xmv = TEdata_noFault_train[:,41:52]
data_noFault_train = np.hstack((xmeas, xmv))

#%% scale data
scaler = StandardScaler()
data_train_normal = scaler.fit_transform(data_noFault_train)

#%% decide # of PCs to retain via PCA variance method
pca = PCA().fit(data_train_normal)

explained_variance = 100*pca.explained_variance_ratio_
cum_explained_variance = np.cumsum(explained_variance)

n_comp = np.argmax(cum_explained_variance >= 90) + 1

#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
##                     Monitoring statistics function
## %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

def compute_PCA_monitoring_metrics(pca_model, number_comp, data):
    """ calculate monitoring statistics for given data

    parameters
    -----------
    data: numpy array of shape = [n_samples, n_features]
          Training or test data

    Returns
    ----------
    monitoring_stats: numpy array of shape = [n_samples, 2]

    """

    # data parameters
    n = data.shape[0]

    # model parameters
    V_matrix = pca.components_.T
    P_matrix = V_matrix[:,0:n_comp]

    # model computation
    score = pca.transform(data)
    score_reduced = score[:,0:n_comp]
    data_reconstruct = np.dot(score_reduced, P_matrix.T)

    # T2
    lambda_k = np.diag(pca.explained_variance_[0:n_comp])
    lambda_k_inv = np.linalg.inv(lambda_k)
    T2 = np.zeros((data.shape[0],))
    for i in range(n):
        T2[i] = np.dot(np.dot(score_reduced[i,:],lambda_k_inv),score_reduced[i,:].T)

    # SPE
    error = data - data_reconstruct
    SPE = np.sum(error*error, axis = 1)

    monitoring_stats = np.column_stack((T2, SPE))
    return monitoring_stats

def draw_monitoring_chart(values, CL, yLabel):
    plt.figure()
    plt.plot(values)
    plt.axhline(CL, color = "red", linestyle = "--")
    plt.xlabel('Sample #')
    plt.ylabel(yLabel)
    plt.show()

def draw_PCA_monitoring_charts(PCA_statistics, CLs, trainORtest):
    """ draw monitoring charts for given data

    parameters
    -----------
    PCA_statistics: numpy array of shape = [n_samples, 2]
    CLs: List of control limits
    trainORtest: 'training' or 'test'

    """

    # T2 chart, SPE chart
    draw_monitoring_chart(PCA_statistics[:,0], CLs[0], 'T2 for ' + trainORtest + ' data')
    draw_monitoring_chart(PCA_statistics[:,1], CLs[1], 'SPE for ' + trainORtest + ' data')

#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
##                   Draw monitoring charts for training data
## %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
PCA_statistics_train = compute_PCA_monitoring_metrics(pca, n_comp, data_train_normal)

T2_CL = np.percentile(PCA_statistics_train[:,0], 99)
SPE_CL = np.percentile(PCA_statistics_train[:,1], 99)

draw_PCA_monitoring_charts(PCA_statistics_train, [T2_CL, SPE_CL], 'training')

#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
##                   FAR / FDR computation function
## %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
def compute_alarmRate(monitoring_stats, CLs):
    """ calculate false rate

    parameters
    -----------
    monitoring_stats: numpy array of shape = [n_samples, 2]
    CLs: List of control limits

    Returns
    ----------
    alarmRate: float

    """

    violationFlag = monitoring_stats > CLs
    alarm_overall = np.any(violationFlag, axis=1) # violation of any metric => alarm
    alarmRate = 100*np.sum(alarm_overall)/monitoring_stats.shape[0]

    return alarmRate

#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
##                   Draw monitoring charts for test data
## %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
# fetch data
TEdata_Fault_test = np.loadtxt('d05_te.dat')

# select data as done in Lee et al.
xmeas = TEdata_Fault_test[:,0:22]
xmv = TEdata_Fault_test[:,41:52]
data_Fault_test = np.hstack((xmeas, xmv))

# scale data
data_test_scaled = scaler.transform(data_Fault_test)

# compute statistics and draw charts
PCA_statistics_test = compute_PCA_monitoring_metrics(pca, n_comp, data_test_scaled)
draw_PCA_monitoring_charts(PCA_statistics_test, [T2_CL, SPE_CL], 'test')

# compute FAR or FDR
alarmRate = compute_alarmRate(PCA_statistics_test[160:,:], [T2_CL, SPE_CL]) # faults start from sample 160
print(alarmRate)


# -*- coding: utf-8 -*-

import numpy as np
from sympy import *
from math import *

from timeit import default_timer as timer

def phix(a, b, c, x0,x): # define função phi(x)

    return a - (b.subs(x,x0)/c.subs(x,x0))

def xProximo(y,Y):

    xR = Y[0,0]

    for i in range(1,Y.shape[1]):

        if(abs(Y[0,i] - y) < abs(xR - y)):
            xR = Y[0,i]
    return xR

def newtonRaphson(fx,dfx,x0,e,c,x):

    phi = None
    d = 0

    while (d < c) :

        phi = phix(x0,fx,dfx,x0,x) # calcula phi(x0)

        if(abs(fx.subs(x,x0)) < e): # checa se a função em x0 é menor ou igual à precisão desejada

            return [phi,0,d]

        x0 = phi # caso f(x) não seja perto de 0 o suficiente, x0 recebe o valor de phi(x0) e segue no laço

        if(d == c-1):

            return [phi,1]

        d+=1

def diferencasDivididas(X,Y):
    if(Y.shape[1] == 1):

        return Y[0]

    else:

        X1 = X[:,1:]
        X0 = X[:,:(X.shape[1]-1)]
        Y1 = Y[:,1:]
        Y0 = Y[:,:(Y.shape[1]-1)]

        d = (diferencasDivididas(X1,Y1) - diferencasDivididas(X0,Y0))/(X[X.shape[1]-1] - X[0])

        return d

start = None
end = None

x = symbols('x')

X = Matrix(eval(input("\n\n   Digite o vetor x: ")))
Y = Matrix(eval(input("   Digite o vetor y: ")))

Xp = ones(X.shape[0],X.shape[1])*x - X[:,:]

Pn = zeros(X.shape[0],X.shape[1])

Pn[0,0] = Y[0,0]

Sn = Y[0,0]

start = timer()

for i in range(1,X.shape[1]):

    p = 1

    for j in range(0,i):

        p *= Xp[0,j]

    Pn[0,i] = p*diferencasDivididas(X[:,:(i+1)],Y[:,:(i+1)])

end = timer()

for i in range(1,Pn.shape[1]):

    Sn += Pn[0,i]

Sn = sympify(Sn)
c = 30
y0 = float(input("   Digite um valor de y para ser testado no polinômio interpolado: "))
e = float(input("   Digite a precisão do x estimado: "))
Sn2 = Sn - y0
print("   Pn(x) = "+str(Sn))
print("   f(xk) = "+str(y0))
print("   xk = "+str(newtonRaphson(Sn2,diff(Sn2,x),xProximo(y0,Y),e,c,x)[0]))
print("   Tempo de execucao total: %e segundos\n\n" % (end - start))


#!\usr\bin\python
"""
File: Diff2

Copyright (c) 2016 Michael Seaman

License: MIT

A class for differentiation, to be used inherited by Backward2.py
Stores the function to be differentiated, and the stepsize h for evaluation
"""

import numpy as np
from unittest import TestCase

class Diff2():
    """
    Class holding a function to be differentiated as well as the stepsize h
    to evaluate from. Diff2 also stores the exact derivative to be checked against
    in the error method.
    Implemented (mostly) from the book
    """
    def __init__(self, f, h=1E-5, dfdx_exact = None):
        self.f = f
        self.h = np.array(h).astype(float)
        self.exact = dfdx_exact

    def error(self, x):
        if self.exact is not None:
            df_numerical = self(x)
            df_exact = self.exact(x)
            return df_exact - df_numerical

class Backward1(Diff2):
    """
    Implements the backward differentiation method for the instantaneous rate
    of change at the point x. Calculated using Euler's method.
    """
    def __call__(self, x):
        f, h = self.f, self.h
        return (f(x) - f(x-h))/h

def linear_func(x):
    return -50*x + 250.4

def dfdx_linear_func(x):
    return -50

class Test_Diff2(TestCase):
    def test_Backward1(self):
        """
        Tests that the backward differentiation method perfectly approximates
        a linear function using the dfdx_exact variable
        """
        d = Backward1(linear_func, dfdx_exact = dfdx_linear_func)
        test_values = np.array([-100, -40, 0, 60, 200])
        d.error = np.vectorize(d.error)

        assert np.all( abs(d.error(test_values)) <= np.full(5,1E-5))


import numpy as np
from numpy import linalg as la

def r_squared(x, y):
    """
    Fit a linear regression to :math:`y` and return the :math:`R^2` statistical measure of a fit of a linear regression

    Args:
        x (``np.ndarray``): The :math:`x` coordinates of the points
        y (``np.ndarray``): The :math:`y` coordinates of the points

    Returns:
         ``float``: The :math:`R^2` measure of a fit. Bounded by :math:`\\left[0, 1\\right]`. The closer :math:`R^2` is
         to :math:`1`, the better the fit.

    """
    x = x.ravel()
    y = y.ravel()
    assert x.ndim == y.ndim
    assert len(x) == len(y)
    n = len(x)
    xx = np.stack((np.ones(n), x))
    w, ssr, _, _ = la.lstsq(xx.T, y, rcond=None)
    if ssr.size == 0:
        ssr = 0
    sst = np.var(y, ddof=n - 1)
    r2_1 = (1 - ssr / sst).item()
    corr = np.corrcoef(w @ xx, y)[0, 1]
    r2_2 = corr**2
    assert np.allclose(r2_1, r2_2)
    return ((r2_1 + r2_2) / 2).item()

def ols_swiping(x, y, **kwargs):
    """
    Performs OLS swiping method.

    By first selecting a pivot point, all the data points are implicitly split into two parts: the left one and the
    right one. Then, the algorithm regresses a line onto :math:`y` with respect to :math:`x` for both parts using
    ordinary least squares. If both lines fit quite well, meaning the :math:`R^2` for both left and the right fit is
    particularly high, the pivot point is declared as a knee.

    Args:
        x (``np.ndarray``): the :math:`x` coordinates of the points
        y (``np.ndarray``): the :math:`y` coordinates of the points
        **kwargs: possible additional arguments (none are used)

    Returns:
        ``int``: the index of the knee
    """
    assert len(kwargs) == 0
    n = len(x)
    # some python magic
    # generator of all the splits, linear regressions and the sums of particular r2 coefficients
    results = ((i, r_squared(x[: i + 1], y[: i + 1]) + r_squared(x[i:], y[i:])) for i in range(1, n - 1))
    # the values are only calculated as the generator is consumed :))
    return min(results, key=lambda t: t[1])[0]


import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
from scipy.stats import binom
from scipy import linalg
from scipy.sparse.linalg import expm_multiply
from scipy.sparse import csc_matrix
from scipy.special import comb
import math
import time

def hypercube(n_dim):
    n = n_dim - 1
    sigma_x = np.array([[0, 1],
                        [1, 0]])
    A = sigma_i(sigma_x, 0, n)

    for i in range(1, n_dim):
        A += sigma_i(sigma_x, i, n)
    return -1 * A

def sigma_i(sigma_x, i, n):
    if i > 0:
        out = np.eye(2)
        for j_before in range(i - 1):
            out = np.kron(out, np.eye(2))
        out = np.kron(out, sigma_x)
    else:
        out = sigma_x
    for j_after in range(n - i):
        out = np.kron(out, np.eye(2))
    return out

def quantum_walk_hypercube(N, H, psi0, timesteps, normalise):
    psiN = expm_multiply(-(1j) * timesteps * H, psi0)

    prob = np.real(np.conj(psiN) * psiN)

    result = np.zeros(N + 1)
    normalise_array = np.zeros(N+1)

    for i, probability in enumerate(prob):
        binary_i = bin(i)
        i_ones = [ones for ones in binary_i[2:] if ones == '1']
        num_ones = len(i_ones)
        result[num_ones] += probability
        if normalise:
            normalise_array[num_ones] += 1

    if normalise:
        result = result/normalise_array

    return result

def run_many_walks(n, time_limit, gamma, normalise=False):
    P = 2 ** n  # number of positions
    A = hypercube(n)
    marked_state = np.zeros((2 ** n, 2 ** n))
    marked_state[0, 0] = 1
    H = gamma * (A - n * np.eye(2 ** n)) - marked_state  # not sure if marked_node should also be multiplied by gamma

    psi0 = np.ones(P) * (1 / np.sqrt(2 ** n))
    output = np.zeros((time_limit + 1, n + 1))
    for timesteps in range(0, time_limit + 1):
        output[timesteps] = quantum_walk_hypercube(n, H, psi0, timesteps, normalise=normalise)
        print(sum(output[timesteps]))
    return output

def plot_furthest_qubit_prob(timesteps, data):
    plt.figure()
    plt.plot(range(timesteps + 1), data[:, -1])
    plt.xlim(0, timesteps)
    plt.xticks(range(0, timesteps + 1, 5))
    plt.ylim(0, 1)
    plt.yticks([0, 0.2, 0.4, 0.6, 0.8, 1])
    plt.show()

def plot_nearest_qubit_prob(timesteps, data):
    plt.figure()
    plt.plot(range(timesteps + 1), data[:, 0])
    plt.xlim(0, timesteps)
    plt.xticks(range(0, timesteps + 1, 5))
    plt.ylim(0, 1)
    plt.yticks([0, 0.2, 0.4, 0.6, 0.8, 1])
    plt.show()

def plot_prob_heatmap(data, N, timesteps):
    fig, ax = plt.subplots()
    im = ax.imshow(data.T, interpolation="gaussian", cmap=plt.get_cmap('plasma'))
    ax.set_xlabel("Time, t")
    ax.set_ylabel("Hamming distance, d")
    plt.yticks(range(0, N + 1, 2))
    plt.xticks(range(0, timesteps + 1, 5))
    ax.invert_yaxis()

    cb = fig.colorbar(cm.ScalarMappable(cmap=plt.get_cmap('plasma')))
    cb.set_label('Normalised probability, P(d, t)')

    plt.show()

def optimal_gamma(n):
    N = 2**n
    gam = 0
    for r in range(1, n+1):
        gam += comb(n, r) * (1/r)
    gam = (1/2) * (1/N) * gam
    return gam

if __name__ == '__main__':
    time_start = time.time()

    n = 8  # number of dimensions of hypercube
    timesteps = 50
    gamma = optimal_gamma(n)    # hopping rate
    print("gamma:", gamma)

    data = run_many_walks(n, timesteps, gamma, normalise=True)  # 2D array of [timesteps_run, probability_at_distance_of_index]

    time_end = time.time()
    print("runtime:", time_end - time_start)

    #plot_furthest_qubit_prob(timesteps, data)
    plot_nearest_qubit_prob(timesteps, data)
    plot_prob_heatmap(data, n, timesteps)


# -*- coding: utf-8 -*-
"""
@author: Makan Arastuie
"""

import numpy as np
from os.path import join
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from scipy.sparse.linalg import svds
from sklearn.preprocessing import normalize

def spectral_cluster(adj, num_classes=2, n_kmeans_init=10, normalize_z=True, verbose=False, plot_eigenvalues=False,
                     plot_save_path=''):
    """
    Runs spectral clustering on weighted or unweighted adjacency matrix

    :param adj: weighted, unweighted or regularized adjacency matrix
    :param num_classes: number of classes for spectral clustering
    :param n_kmeans_init: number of initializations for k-means
    :param normalize_z: If True, vector z is normalized to sum to 1
    :param verbose: if True, prints the eigenvalues
    :param plot_eigenvalues: if True, plots the first `num_classes` singular values
    :param plot_save_path: directory to save the plot

    :return: predicted clustering membership
    """
    # Compute largest num_classes singular values and vectors of adjacency matrix
    u, s, v = svds(adj, k=num_classes)
    v = v.T

    if verbose:
        print("Eigenvalues: \n", s)

    if plot_eigenvalues:
        fig, ax = plt.subplots()
        plt.scatter(np.arange(num_classes, 0, -1), s, s=80, marker='*', color='blue')
        plt.xlabel('Rank', fontsize=24)
        plt.ylabel('Singular Values', fontsize=24)
        plt.grid(True)
        ax.tick_params(labelsize=20)
        plt.tight_layout()
        plt.savefig(join(plot_save_path, 'singular_values.pdf'))
        plt.show()

    # Sort in decreasing order of magnitude
    sorted_ind = np.argsort(-s)
    u = u[:, sorted_ind]
    v = v[:, sorted_ind]

    z = np.c_[u, v]

    if normalize_z:
        z = normalize(z, norm='l2', axis=1)

    km = KMeans(n_clusters=num_classes, n_init=n_kmeans_init)
    cluster_pred = km.fit_predict(z)

    return cluster_pred

def regularized_spectral_cluster(adj, num_classes=2, tau=None, n_kmeans_init=10, normalize_z=True):
    """
    Runs regularized spectral clustering on weighted or unweighted adjacency matrix

    :param adj: weighted, unweighted or regularized adjacency matrix
    :param num_classes: number of classes for spectral clustering
    :param tau: regularization parameter
    :param n_kmeans_init: number of initializations for k-means
    :param normalize_z: If True, vector z is normalized to sum to 1

    :return: predicted clustering membership
    """
    node_outdegree = np.sum(adj, axis=1)
    node_indegree = np.sum(adj, axis=0)

    if tau is None:
        tau = np.mean(node_outdegree)

    o_t = np.diag(1 / np.sqrt(node_outdegree + tau))
    p_t = np.diag(1 / np.sqrt(node_indegree + tau))
    l_t = o_t.dot(adj).dot(p_t)

    return spectral_cluster(l_t, num_classes, n_kmeans_init, normalize_z)


import matplotlib.pyplot as plt
import numpy as np

# 根据均值、标准差,求指定范围的正态分布概率值
def norm_fun(x, mu, sigma):
    pdf = np.exp(-((x - mu) ** 2) / (2 * sigma ** 2)) / (sigma * np.sqrt(2 * np.pi))
    return pdf

if __name__ == '__main__':
    # result = np.random.randint(-65, 80, size=100) # 最小值,最大值,数量
    result = np.random.normal(15, 44, 100)  # 均值为0.5,方差为1
    print(result)
    x = np.arange(min(result), max(result), 0.1)
    # 设定 y 轴，载入刚才的正态分布函数
    print(result.mean(), result.std())
    y = norm_fun(x, result.mean(), result.std())
    plt.plot(x, y)  # 这里画出理论的正态分布概率曲线
    # 这里画出实际的参数概率与取值关系
    plt.hist(result, bins=10, rwidth=0.8, density=True)  # bins个柱状图,宽度是rwidth(0~1),=1没有缝隙
    plt.title('distribution')
    plt.xlabel('temperature')
    plt.ylabel('probability')
    # 输出
    plt.show()  # 最后图片的概率和不为1是因为正态分布是从负无穷到正无穷,这里指截取了数据最小值到最大值的分布


#
# main.py
#

import os
import math
import implementation
import numpy as np
import scipy.constants
import matplotlib.pyplot as plot

frequency  = 300*math.pow(10, 6)
wavelength = float(scipy.constants.c)/frequency

'''
Plot the current distribution of a half-wavelength dipole antenna
along the z axis using 3, 7 and 19 triangular base functions. Also,
print the input impedance of the configurations.
'''

plots = []
impedances = []

segments_count = [3, 7, 19]
antenna_length = wavelength*(0.5)
antenna_radius = wavelength*math.pow(10, -4)

for count in segments_count:

    powered_segment = (count//2)+1
    half_base_width = float(antenna_length)/(count+1)

    I = implementation.solve_dipole_antenna_mom(
        frequency=frequency,
        antenna_length=antenna_length,
        antenna_radius=antenna_radius,
        segments_count=count,
        powered_segment=powered_segment
    )

    I_in = I[powered_segment-1]
    Z_in = 1/I_in

    I_absolute = np.absolute(I)
    I_mV = [(i*1000) for i in I_absolute]
    I_mV = [0] + I_mV + [0]

    x_neg = [ ( ((n*half_base_width)-(antenna_length/2)) / wavelength)  for n in range((count+2)//2)]
    x_pos = [-x for x in x_neg]
    x_rev = [x for x in reversed(x_pos)]
    x = x_neg + [0] + x_rev

    plots.append([x, I_mV])
    impedances.append(Z_in)

plot.figure()
plot.plot(plots[0][0], plots[0][1], "g-+")
plot.plot(plots[1][0], plots[1][1], "b-x")
plot.plot(plots[2][0], plots[2][1], "r-")
plot.legend(["N=3", "N=7", "N=19"], loc="upper right")
plot.title("Current Distribution (L = λ/2)")
plot.xlabel("Z/λ")
plot.ylabel("|I| (mA)")
plot.savefig("graphs/half-wavelength-currents.pdf", bbox_inches="tight")

print("")
print("Half-wavelength dipole antenna input impedance:")
for i in range(len(segments_count)):
    print(format(segments_count[i], '02d') + " " + str(impedances[i]))

'''
Plot the inpute impedance active and reactive components for a
half-wavelength dipole antenna using 3..49 triangular base functions.
'''

actives = []
reactives = []

segments_count = [x for x in range(3, 50) if (x%2) != 0]
antenna_length = wavelength*(0.5)
antenna_radius = wavelength*math.pow(10, -4)

for count in segments_count:

    powered_segment = (count//2)+1
    half_base_width = float(antenna_length)/(count+1)

    I = implementation.solve_dipole_antenna_mom(
        frequency=frequency,
        antenna_length=antenna_length,
        antenna_radius=antenna_radius,
        segments_count=count,
        powered_segment=powered_segment
    )

    I_in = I[powered_segment-1]
    Z_in = 1/I_in

    actives.append([count, Z_in.real])
    reactives.append([count, Z_in.imag])

plot.figure()
plot.plot([x[0] for x in actives], [x[1] for x in actives], "g-")
plot.plot([x[0] for x in reactives], [x[1] for x in reactives], "b-")
plot.legend(["R (Ω)", "X (Ω)"], loc="center right")
plot.title("Input Impedance (L = λ/2)")
plot.xlabel("Z/λ")
plot.savefig("graphs/half-wavelength-impedances.pdf", bbox_inches="tight")

'''
Plot the current distribution of a wavelength dipole antenna along
the z axis using 3, 7 and 19 triangular base functions. Also, print
the input impedance of the configurations.
'''

plots = []
impedances = []

segments_count = [3, 7, 19]
antenna_length = wavelength
antenna_radius = wavelength*math.pow(10, -4)

for count in segments_count:

    powered_segment = (count//2)+1
    half_base_width = float(antenna_length)/(count+1)

    I = implementation.solve_dipole_antenna_mom(
        frequency=frequency,
        antenna_length=antenna_length,
        antenna_radius=antenna_radius,
        segments_count=count,
        powered_segment=powered_segment
    )

    I_in = I[powered_segment-1]
    Z_in = 1/I_in

    I_absolute = np.absolute(I)
    I_mV = [(i*1000) for i in I_absolute]
    I_mV = [0] + I_mV + [0]

    x_neg = [ ( ((n*half_base_width)-(antenna_length/2)) / wavelength)  for n in range((count+2)//2)]
    x_pos = [-x for x in x_neg]
    x_rev = [x for x in reversed(x_pos)]
    x = x_neg + [0] + x_rev

    plots.append([x, I_mV])
    impedances.append(Z_in)

plot.figure()
plot.plot(plots[0][0], plots[0][1], "g-+")
plot.plot(plots[1][0], plots[1][1], "b-x")
plot.plot(plots[2][0], plots[2][1], "r-")
plot.legend(["N=3", "N=7", "N=19"], loc="upper right")
plot.title("Current Distribution (L = λ)")
plot.xlabel("Z/λ")
plot.ylabel("|I| (mA)")
plot.savefig("graphs/wavelength-currents.pdf", bbox_inches="tight")

print("")
print("Wavelength dipole antenna input impedance:")
for i in range(len(segments_count)):
    print(format(segments_count[i], '02d') + " " + str(impedances[i]))
print("")

'''
Plot the inpute impedance active and reactive components for a
wavelength dipole antenna using 3..49 triangular base functions.
'''

actives = []
reactives = []

segments_count = [x for x in range(3, 50) if (x%2) != 0]
antenna_length = wavelength
antenna_radius = wavelength*math.pow(10, -4)

for count in segments_count:

    powered_segment = (count//2)+1
    half_base_width = float(antenna_length)/(count+1)

    I = implementation.solve_dipole_antenna_mom(
        frequency=frequency,
        antenna_length=antenna_length,
        antenna_radius=antenna_radius,
        segments_count=count,
        powered_segment=powered_segment
    )

    I_in = I[powered_segment-1]
    Z_in = 1/I_in

    actives.append([count, Z_in.real])
    reactives.append([count, Z_in.imag])

plot.figure()
plot.plot([x[0] for x in actives], [x[1] for x in actives], "g-")
plot.plot([x[0] for x in reactives], [x[1] for x in reactives], "b-")
plot.legend(["R (Ω)", "X (Ω)"], loc="center right")
plot.title("Input Impedance (L = λ/2)")
plot.xlabel("Z/λ")
plot.savefig("graphs/wavelength-impedances.pdf", bbox_inches="tight")

'''
Delete bytecode files and the cache folder.
'''

os.system("find . -type f -name \"*.pyc\" -delete")
os.system("rm -rf __pycache__")


import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0,4,10001)
y = 0*x
y[np.logical_and(1<x,x<=2)] = x[np.logical_and(1<x,x<=2)]-1
y[np.logical_and(2<x,x<=3)] = 1 - np.sqrt(.3-.25) + np.sqrt(0.3 - (x[np.logical_and(2<x,x<=3)]-2.5)**2)
y[x>3] = 1

fig = plt.figure(figsize=(4, 3))
plt.plot(x,y, linewidth=2.0)
# plt.gca().set_aspect('equal', adjustable='box')
plt.xticks([0,1,2,3,4])
plt.tick_params(labelsize=14, left="off", labelleft="off")
plt.xlabel("time", fontsize=14)
plt.ylabel("distance", fontsize=14)
fig.set_tight_layout(True)
plt.savefig("calcQ.pdf")

fig = plt.figure(figsize=(4, 3))
# plt.plot(x[1:],np.diff(y), linewidth=2.0)
x = x[1:]
dydx = np.diff(y)
d1 = x<1
d2 = np.logical_and(1<x,x<2)
d3 = np.logical_and(2<x,x<3)
d4 = x>3
plt.plot(x[d1],dydx[d1], 'b', linewidth=2.0)
plt.plot(x[d2],dydx[d2], 'b', linewidth=2.0)
plt.plot(x[d3],dydx[d3], 'b', linewidth=2.0)
plt.plot(x[d4],dydx[d4], 'b', linewidth=2.0)

plt.xticks([0,1,2,3,4])
plt.yticks([0])
plt.tick_params(labelsize=14)
plt.xlabel("time", fontsize=14)
plt.ylabel("velocity", fontsize=14)
fig.set_tight_layout(True)
plt.savefig("calcA.pdf")