# Create list baseball
import numpy as np
baseball = [180, 215, 210, 210, 188, 176, 209, 200]

# Import the numpy package as np

# Create a numpy array from baseball: np_baseball
np_baseball = np.array(baseball)

# Print out type of np_baseball
print(type(np_baseball))

# height is available as a regular list

# Import numpy

# Create a numpy array from height_in: np_height_in
np_height_in = np.array(height_in)

# Print out np_height_in
print(np_height_in)

# Convert np_height_in to m: np_height_m
np_height_m = np_height_in * 0.0254

# Print np_height_m
print(np_height_m)

# height and weight are available as regular lists

# Import numpy

# Create array from height_in with metric units: np_height_m
np_height_m = np.array(height_in) * 0.0254

# Create array from weight_lb with metric units: np_weight_kg
np_weight_kg = np.array(weight_lb)*0.453592

# Calculate the BMI: bmi
bmi = np_weight_kg/(np_height_m**2)

# height and weight are available as a regular lists

# Import numpy

# Calculate the BMI: bmi
np_height_m = np.array(height_in) * 0.0254
np_weight_kg = np.array(weight_lb) * 0.453592
bmi = np_weight_kg / np_height_m ** 2

# Create the light array
light = bmi < 21

# Print out light
print(light)

# height and weight are available as a regular lists

# Import numpy

# Store weight and height lists as numpy arrays
np_weight_lb = np.array(weight_lb)
np_height_in = np.array(height_in)

# Print out the weight at index 50
print(np_weight_lb[50])

# Print out sub-array of np_height_in: index 100 up to and including index 110
print(np_height_in[100:111])

# Create baseball, a list of lists
baseball = [[180, 78.4],
            [215, 102.7],
            [210, 98.5],
            [188, 75.2]]

# Import numpy

# Create a 2D numpy array from baseball: np_baseball
np_baseball = np.array(baseball)

# Print out the type of np_baseball
print(type(np_baseball))

# baseball is available as a regular list of lists

# Import numpy package

# Create a 2D numpy array from baseball: np_baseball
np_baseball = np.array(baseball)

# Print out the shape of np_baseball
print(np_baseball.shape)

# baseball is available as a regular list of lists

# Import numpy package

# Create np_baseball (2 cols)
np_baseball = np.array(baseball)

# Print out the 50th row of np_baseball
print(np_baseball[49, :])

# Select the entire second column of np_baseball: np_weight_lb
np_weight_lb = np_baseball[:, 1]

# Print out height of 124th player
# baseball is available as a regular list of lists
# updated is available as 2D numpy array

# Import numpy package

# Create np_baseball (3 cols)
np_baseball = np.array(baseball)

# Print out addition of np_baseball and updated
print(np_baseball+updated)

# Create numpy array: conversion
conversion = np.array([0.0254, 0.453592, 1])

# np_baseball is available

# Import numpy

# Create np_height_in from np_baseball
np_height_in = np_baseball[:, 0]

# Print out the mean of np_height_in
print(np_height_in.mean())

# Print out the median of np_height_in
print(np.median(np_height_in))

# np_baseball is available

# Import numpy

# Print mean height (first column)
avg = np.mean(np_baseball[:, 0])
print("Average: " + str(avg))

# Print median height. Replace 'None'
med = np.median(np_baseball[:, 0])
print("Median: " + str(med))

# Print out the standard deviation on height. Replace 'None'
stddev = np.std(np_baseball[:, 0])
print("Standard Deviation: " + str(stddev))

# Print out correlation between first and second column. Replace 'None'
corr = np.corrcoef(np_baseball[:, 0], np_baseball[:, 1])
print("Correlation: " + str(corr))

# heights and positions are available as lists

# Import numpy

# Convert positions and heights to numpy arrays: np_positions, np_heights
np_positions = np.array(positions)
np_heights = np.array(heights)

# Heights of the goalkeepers: gk_heights
gk_heights = np_heights[np_positions == 'GK']

# Heights of the other players: other_heights
other_heights = np_heights[np_positions != 'GK']

# Print out the median height of goalkeepers. Replace 'None'
print("Median height of goalkeepers: " + str(np.median(gk_heights)))

# Print out the median height of other players. Replace 'None'
print("Median height of other players: " + str(np.median(other_heights)))


import numpy as np

# ==================== Question 5 ====================
def is_separable_filter(h: np.ndarray) -> bool:
    """
    Return True if the given filter h is separable, false otherwise.
    If the filter h is separable, then also print the corresponding horizontal
    and vertical filters.

    :param h: the given filter
    :return: True if the filter is separable, False otherwise
    """
    u, s, v = np.linalg.svd(h, full_matrices=True, compute_uv=True)
    # since we're using float instead of fractions, we will use
    # a relatively small epsilon (e^{-12}) to check for rank
    k = np.nonzero(s < 1e-12)[0][0]
    if k == 1:
        # Use np slicing instead of indexing to retain matrix shape
        vertical_filter = u[:, :1] * s[0] ** .5
        horizontal_filter = v[:1, :] * s[0] ** .5
        print(vertical_filter)
        print(horizontal_filter)
    return k == 1

if __name__ == '__main__':
    print("{0} Question 5 {0}".format("=" * 20))
    print("{0} Separable {0}".format("=" * 10))
    separable_filter = np.asarray([[1, 2, 1],
                                   [2, 4, 2],
                                   [1, 2, 1]]) / 16
    print(is_separable_filter(separable_filter))
    print("{0} Inseparable {0}".format("=" * 10))
    inseparable_filter = np.asarray([[0, -1, 0],
                                     [-1, 5, -1],
                                     [0, -1, 0]])
    print(is_separable_filter(inseparable_filter))


import numpy as np

NDIM = 4                                # number of dimensions of the domain of the MVN PDF
MEAN =  np.double([-10, 15., 20., 0.0]) # This is the mean of the MVN PDF.
COVMAT = np.double( [ [1.0,.45,-.3,0.0] # This is the covariance matrix of the MVN PDF.
                    , [.45,1.0,0.3,-.2]
                    , [-.3,0.3,1.0,0.6]
                    , [0.0,-.2,0.6,1.0]
                    ] )

INVCOV = np.linalg.inv(COVMAT) # This is the inverse of the covariance matrix of the MVN distribution.

# The following is the log of the coefficient used in the definition of the MVN.

MVN_COEF = NDIM * np.log( 1. / np.sqrt(2.*np.pi) ) + np.log( np.sqrt(np.linalg.det(INVCOV)) )

# the logarithm of objective function: log(MVN)

def getLogFunc(point):
    '''
    Return the logarithm of the MVN PDF.
    '''
    normedPoint = MEAN - point
    return MVN_COEF - 0.5 * ( np.dot(normedPoint,np.matmul(INVCOV,normedPoint)) )

import paramonte as pm

pmpd = pm.ParaDRAM() # define a ParaMonte sampler instance

pmpd.mpiEnabled = True # This is essential as it enables the invocation of the MPI-parallelized ParaDRAM routines.

pmpd.spec.overwriteRequested = True # overwrite existing output files if needed
pmpd.spec.randomSeed = 3751 # initialize the random seed to generate reproducible results.
pmpd.spec.outputFileName = "./out/mvn_parallel_singleChain"
pmpd.spec.progressReportPeriod = 20000
pmpd.spec.chainSize = 30000 # the default 100,000 unique points is too large for this simple example.

# call the ParaDRAM sampler

pmpd.runSampler ( ndim = 4
                , getLogFunc = getLogFunc
                )


def plotGauss(mean_0,mean_1,sd_0,sd_1,rho,vminmax=None,\
                file=None,title=None):
   # Import some libraries, in case you haven't yet imported them
   import matplotlib.pyplot as plt
   import numpy as np

   # size of grid
   N = 1000
   # generate grid (NB -1 to 1 here)
   coords = 2. * (np.arange(N+1)/float(N) - 0.5)
   x0, x1 = np.meshgrid(coords,coords)
   x = np.array([x0, x1])
   dx = np.array([x0[0,1] - x0[0,0], x1[1,0] - x1[0,0]])
   grid = dx[0] * dx[1]

   # set B
   b01 = b10 = rho * sd_0 * sd_1
   b00 = sd_0**2
   b11 = sd_1**2
   B = np.matrix([[b00,b01],[b10,b11]])
   # set xb: the mean
   xb = np.array([mean_0,mean_1])

   xxb = np.zeros_like(x)
   for i in range(xb.shape[0]): xxb[i,...] = xb[i]
   e = x - xxb

   n = np.shape(B)[0]
   # inverse of B
   BI = B.I
   # scaling term
   scale_1 = (2.*np.pi)**(n/2) * np.sqrt(np.linalg.det(B))
   gauss = np.exp(-0.5 * ((e[0,...] * BI[0,0] + e[1,...] * BI[0,1])* e[0,...]     \
                          + (e[0,...] * BI[1,0] + e[1,...] * BI[1,1])* e[1,...])) \
                          / scale_1

   # check integral
   print ('integral of Gaussian:',gauss.sum() * grid)

   # plot
   plt.clf()
   if title:
       plt.title(title)
   #if len(list(vminmax)):
   #    plt.imshow(gauss,origin='lower',interpolation='nearest', \
   #                    vmin=vminmax[0],vmax=vminmax[1],\
   #                    extent=[x0.min(),x0.max(),x1.min(),x1.max()])
   #else:
   plt.imshow(gauss,origin='lower',interpolation='nearest', \
                       extent=[x0.min(),x0.max(),x1.min(),x1.max()])
   plt.colorbar()
   if file == None:
       plt.show()
   else:
       plt.savefig(file)


import numpy as np
import matplotlib.pyplot as plt
x0 = float(input('Enter initial position(x0 = 1 ,-1 or 1): '))       # Initial position

v0 = float(input('Enter initial velocity (v0 = 0.1, 0.1 or 10): '))  # Initial Velocity
t1 = 0
tn = 100

h = 0.01

"""
''While using third initial condition set tn = 10 and h = 0.001''
"""
n = (tn-t1)/h
x = np.zeros(int(n))
v = np.zeros(int(n))
# force
force0 = -4 *x0*(x0**2 -1)
force = np.zeros(int(n))
force[0] = force0
x[0] = x0
v[0] = v0
def force(x):
  return -4 * x * (x**2 -1)

for i in range(int(n-1)):

  s1 = force(x[i])
  s2 = force(x[i] + h/2)
  s3 = force(x[i] + h/2)
  s4 = force(x[i]+h)
  s = (s1+2*s2+2*s3+s4)/6
  v[i+1] = v[i] + s * h
  x[i+1] = x[i] + v[i] *h

                                    #--------- plotting----------
plt.figure("Phase space Trajectory RK4 (x0, p0)=(1, 0.1)", figsize =(7,5))
plt.plot(x, v, color = 'blue')

plt.xlabel('position (x)')
plt.ylabel('Velocity (v)')
plt.title("Phase space Trajectory RK4 (x0, p0)=" +"("+str(x0) + ',' + str(v0)+")")
# plt.savefig(f"Phase-space-Trajectory-RK4-{(x0, v0)}.png")
plt.show()

# plt.show(block =False)
# plt.pause(0.0001)
# plt.clf()


import numpy as np
from scipy.optimize import curve_fit
import icf

# This function will generate a perfect Gaussian
# You can replace this function with any other you want to fit with...
def gaussian(x, *params):

	A = params[0]
	x0 = params[1]
	c = params[2]

	return A*np.exp(-(x-x0)**2/(2*c*c))

#
# This section will make a numpy array containing a gaussian
#

# This makes a numpy array with 100 equally spaced points between 0 and 4
xdata = np.linspace(0,4,100)

# This makes a gaussian using these x points
ydata = gaussian(xdata, 3, 2, 0.2)

# Lets add some noise
for i in range(len(ydata)):
	ydata[i] +=  0.4*(np.random.random_sample()-0.5)

#
# This section will do a fit
#

# This does the fit, and returns the fit parameters and the covariances

guess = [1,1,1]
print("Our initial guess is", guess)
popt, pcov = curve_fit(gaussian, xdata, ydata, p0=guess)

for i in range(len(popt)):
	print ("Parameter",i,":",popt[i],"+/-",np.sqrt(pcov[i][i]))

print("Fit parameters : ", popt)
print("Fit standard deviations : ", np.sqrt(np.diag(pcov)))

# This generates a new list with a Gaussian using the identified fit parameters
# This data is therefore the best fit curve
yfit = gaussian(xdata, *popt)

print("R^2 = ", icf.r_squared(ydata, yfit))

# This will plot the output, both the original data and the best fit, as well as a residual
# Note this is a special plotting routine written for the icf labs, hence the 'icf' prefix
# The source code can be found in icf.py if you want to copy/alter it

icf.fit_plot(xdata, ydata, yfit)


#!/usr/bin/python3
import numpy as np

def deriving_finite_difference_approximations(hs, order=1, errors=1):
    '''Deriving finite difference approximations
    using the method of undetermined coefficients.

    Example
        >>> # Du(x) = au(x) + bu(x-h) + cu(x-2h)
        >>> hs = [0, -1, -2]
        >>> order = 1
        >>> deriving_finite_difference_approximations(hs, order)
        ([1.5, -2.0, 0.5], [-0.3333333333333333])
        >>> # a, b, c = (1.5, -2.0, 0.5) / h^order
        >>> # Du(x)-u'(x) = -0.333 * h^2 * u^(3)(x)
        >>> # h^2: 2 = len(hs) + ith - order where errors[ith]=-0.333
    '''
    # the method of undetermined coefficients
    length = len(hs)
    _hs = np.ones(length)
    A = np.ndarray((length, length))
    A[0, :] = 1
    for ith in range(1, length):
        _hs *= hs
        A[ith, :] = _hs
    b = np.zeros(length)
    b[order] = np.math.factorial(order)
    coefficients = np.linalg.solve(A, b)
    # errors
    _errors = [None] * errors
    denominator = np.math.factorial(length-1)
    for ith in range(errors):
        denominator *= length + ith
        _hs *= hs
        _errors[ith] = sum(coefficients*_hs) / denominator
    return coefficients.tolist(), _errors

if __name__ == '__main__':
    hs = [0, -1, -2]
    order = 1
    c, e = deriving_finite_difference_approximations(hs, order, 3)
    print(c, e)

    hs = [-1, 0, 1]
    order = 2
    c, e = deriving_finite_difference_approximations(hs, order, 3)
    print(c, e)


import numpy as np
from sympy import Matrix

A = np.array([[2, 3, 1, 0], [4, -1, 9, 0], [3, 8, -2, 0], [1, -2, 4, 0]])
# 将numpy.array转为sympy.Matrix
MA = Matrix(A)
print("------------------行简化阶梯型-------------------")
print(MA.rref()) # 行简化阶梯型

print("------------------对角化矩阵-------------------")
M = Matrix([[3,-2,4,-2],[5,3,-3,-2],[5,-2,2,-2],[5,-2,-3,3]])
P, D = M.diagonalize() # 对角化矩阵
print(P)
print("对角矩阵 D：")
print(D)

print("------------------LU 分解-------------------")
print(MA.LUdecomposition()) # LU 分解
print("------------------QR 分解-------------------")
print(MA.QRdecomposition()) # QR 分解
# (把矩阵分解成一个正交矩阵与一个上三角矩阵的积 ,Q 是正交矩阵（意味着 QTQ = I）而 R 是上三角矩阵,此外，原矩阵A不必为正方矩阵； 如果矩阵A大小为n*m，则矩阵Q大小为n*m，矩阵R大小为m*m。)


import numpy as np

#Funcion que calcula la matriz resultante C despues de aplicar la operacion convolucion de A*B
def convolucion(A, B):
    C_filas = len(A) - len(B) + 1
    C_columnas = len(A[0]) - len(B[0]) + 1
    C = np.zeros((C_filas, C_columnas))
    for i in range(len(C)):
        for j in range(len(C[0])):
            suma = 0
            for n in range(len(B)):
                for m in range(len(B[0])):
                    suma += A[n + i][m + j] * B[n][m]
            C[i][j] = suma
    return C

Matriz1 = [[6, 9, 0, 3], [8, 4, 9, 1], [4, 1, 3, 12], [3, 2, 1, 100]]
Filtro = [[1, 0, 2], [5, 0, 9], [6, 2, 1]]

A = np.array(Matriz1)
B = np.array(Filtro)

print('Ejemplo 1')
print(convolucion(A, B))

print('\nEjemplo 2')

Matriz2 = [[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11, 12], [0, 0, 1, 16, 17, 18] ,[0, 1, 0, 7, 23, 24], [1, 7, 6, 5, 4, 3]]
Filtro2 = [[1, 1, 1], [0, 0, 0], [2, 10, 3]]

A2 = np.array(Matriz2)
B2 = np.array(Filtro2)

print(convolucion(A2, B2))


from sympy import symbols, Matrix, linsolve
import sympy

w, x, y, z = symbols("w,x,y,z")

def test1(): # 线性方程有唯一解

    A = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 10]])
    b = Matrix([3, 6, 9])
    res = linsolve((A, b), [x, y, z])
    for i in res.args[0]:
        print(i.subs(z, 0))

def test2(): #线性方程有多解

    A = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
    b = Matrix([3, 6, 9])
    res = linsolve((A, b), x, y, z)
    for i in res.args[0]:
        print(i.subs(z, 0))

def test3(): #线性方程无解

    A = Matrix([[0, 0, 0], [0, 0, 0], [0, 0, 0]])
    b = Matrix([3, 6, 9])
    res = linsolve((A, b), x, y, z)
    print(res,isinstance(res, sympy.sets.sets.EmptySet))

def test4():

    A = Matrix([[1, 2, 3, 2], [4, 5, 6, 3], [7, 8, 9, 3]])
    b = Matrix([3, 6, 9])
    res = linsolve((A, b), w, x, y, z)
    print(A)
    print(b)
    print(res)

if __name__ == "__main__":
    test4()


import numpy as np

def compute_Z(X, centering=True, scaling=False):
    # This function is used to center each of the feature with its mean
    # It is also used to standardize the features based on the inputs
    # centering and scaling
    X = np.array(X, dtype=np.float64)
    if centering:
        # if centering is true, then we subtract each feature with the respective feature mean
        means = np.mean(X, axis=0, dtype=np.float64)
        for i in range(X.shape[1]):
            X[:,i] -= means[i]

    if scaling:
        # if scaling is true, then we standardize the feature,
        # which is achieved by dividing each of the feature with their
        # standard deviation
        std = np.std(X, axis=0, dtype=np.float64)
        for i in range(X.shape[1]):
            X[:,i] /= std[i]

    return X

def compute_covariance_matrix(Z):
    # This function is used to compute the co-variance matrix
    # This is achieved by the dot product of transpose(Z).Z
    COV = np.dot(Z.T, Z)
    return COV

def find_pcs(COV):
    # This function is used to find the principal components
    # This function returns the principal components based
    # on the descending order of the respective eigen values

    # The linalg.eig function returns the eigen values L and the eigen vectors PSC
    # The ith column of the PSC is the ith eigen vector coreesponding to the ith eigen value
    L, PSC = np.linalg.eig(COV)

    # if a=[1,2,3] and b=[[1,2,3], [4,5,6], [7,8,9]]
    # then list(zip(a,b)) = [(1, [1,2,3]), (2, [4,5,6]), (3, [7,8,9])]
    zipped_list = zip(L, PSC.T)

    # Here we are sorting the eigen values and the eigen vectors in the decreasing order
    zipped_list = sorted(zipped_list, key = lambda item:item[0], reverse=True)

    # We are unzipping the zipped list
    L, PSC = list(zip(*zipped_list))[:]

    # Converting the elements back to matrix format
    L = np.array(L, dtype=np.float64)
    PSC = np.array(PSC).T
    return (L, PSC)

def project_data(Z, PCS, L, k, var):
    # This function is used to project the Z matrix on the eigen vectors
    # If the value of k is zero, then we use the cummulative variance to
    # determine the value of k.
    if k == 0:
        L = np.array(L, dtype=np.float64)
        L_sum = np.sum(L)
        cummulative_var = 0
        for i in range(PCS.shape[1]):
            cummulative_var += (L[i]/L_sum)
            if cummulative_var > var:
                k = i+1
                break

    PCS = PCS[:,:k]
    Z_star = np.dot(Z, PCS)
    return (Z_star)

if __name__ == "__main__":
    X = np.array([[-1, -1],
                 [-1, 1],
                 [1, -1],
                 [1, 1]])
    Z = compute_Z(X)
    COV = compute_covariance_matrix(Z)
    L, PCS = find_pcs(COV)
    Z_star = project_data(Z, PCS, L, 1, 0)
    print(L)
    print(PCS)
    print(Z_star)


import numpy as np
import sympy
from sympy import Matrix, simplify, integrate
sympy.var('xi, le, E, cosr, sinr, rho, A1, A2, Izz1, Izz2')

A = A1 + (A2 - A1)*(xi - (-1))/(1 - (-1))
Izz = Izz1 + (Izz2 - Izz1)*(xi - (-1))/(1 - (-1))
Nu1 = (1-xi)/2
Nu2 = (1+xi)/2

R = Matrix([[  cosr,  sinr , 0, 0, 0, 0],
            [ -sinr,  cosr , 0, 0, 0, 0],
            [ 0,  0 , 1, 0, 0, 0],
            [ 0, 0, 0,  cosr,  sinr , 0],
            [ 0, 0, 0, -sinr,  cosr , 0],
            [ 0, 0, 0, 0,  0 , 1]])

ONE = sympy.Integer(1)
for leg_poly in [True, False]:
    if leg_poly:
        Nv1 = ONE/2 - 3*xi/4 + 1*xi**3/4
        Nb1 = le*(ONE/8 - 1*xi/8 - 1*xi**2/8 + 1*xi**3/8)
        Nv2 = ONE/2 + 3*xi/4 - 1*xi**3/4
        Nb2 = le*(-ONE/8 - 1*xi/8 + 1*xi**2/8 + 1*xi**3/8)
    else: # Hermitian cubic functions
        Nv1 = ONE/4*(1-xi)**2*(2+xi)
        Nb1 = le*1/8*(1-xi)**2*(1+xi)
        Nv2 = ONE/4*(1+xi)**2*(2-xi)
        Nb2 = le*1/8*(1+xi)**2*(xi-1)
    Nu = Matrix([[Nu1, 0,  0, Nu2,  0,  0]])
    Nv = Matrix([[0, Nv1, Nb1,  0, Nv2, Nb2]])
    Nbeta = -(2/le)*sympy.diff(Nv, xi)

    Nuxi = sympy.diff(Nu, xi)
    Nbetaxi = Nbeta.diff(xi)

    Ke = sympy.zeros(6, 6)
    Me = sympy.zeros(6, 6)

    BL = sympy.Matrix([(2/le)*Nuxi,
                       (2/le)*Nbetaxi])
    print('BL (nodal displacements in global coordinates) =', BL*R)

    Ke[:, :] = (2/le)*E*Izz*Nbetaxi.T*Nbetaxi + (2/le)*E*A*Nuxi.T*Nuxi
    Me[:, :] = (le/2)*rho*(A*Nu.T*Nu + A*Nv.T*Nv + Izz*Nbeta.T*Nbeta)

    #NOTE procedure to compute lumped matrix when cross section changes
    x = (xi + 1)*le/2
    mA = integrate((le/2)*rho*A, (xi, -1, 0))
    mB = integrate((le/2)*rho*A, (xi, 0, +1))
    MMIA = integrate((le/2)*rho*(Izz + x**2*A), (xi, -1, 0))
    MMIB = integrate((le/2)*rho*(Izz + (le-x)**2*A), (xi, 0, +1))
    Me_lumped = Matrix([[mA, 0, 0, 0, 0, 0],
                        [0, mA, 0, 0, 0, 0],
                        [0, 0, MMIA, 0, 0, 0],
                        [0, 0, 0, mB, 0, 0],
                        [0, 0, 0, 0, mB, 0],
                        [0, 0, 0, 0, 0, MMIB]])

    # integrating matrices in natural coordinates

    for ind, val in np.ndenumerate(Ke):
        Ke[ind] = simplify(integrate(val, (xi, -1, 1)))

    for ind, val in np.ndenumerate(Me):
        Me[ind] = simplify(integrate(val, (xi, -1, 1)))

    Me_lumped = simplify(Me_lumped)

    print('printing Me')
    print(Me)
    print('printing Me_lumped')
    print(Me_lumped)

    K = simplify(R.T*Ke*R)

    if leg_poly:
        print('K integrated with Legendre polynomial')
    else:
        print('K integrated with Hermitian cubic polynomial')

    print('printing K for code')
    for ind, val in np.ndenumerate(K):
        i, j = ind
        si = 'c1' if i < 3 else 'c2'
        sj = 'c1' if j < 3 else 'c2'
        print('        K[%d+%s, %d+%s]' % (i%3, si, j%3, sj), '+=', K[ind])

    if leg_poly:
        print('M integrated with Legendre polynomial')
    else:
        print('M integrated with Hermitian polynomial')

    print('printing Me for assignment report')
    for ind, val in np.ndenumerate(Me):
        i, j = ind
        if val == 0:
            continue
        print('M_e[%d, %d] =' % (i+1, j+1), end='')
        sympy.print_latex(Me[ind].subs('le', 'l_e'))
        print(r'\\')

    print('printing Me_lumped for assignment report')
    for ind, val in np.ndenumerate(Me_lumped):
        i, j = ind
        if val == 0:
            continue
        print('M_e[%d, %d] =' % (i+1, j+1), end='')
        sympy.print_latex(Me_lumped[ind].subs('le', 'l_e'))
        print(r'\\')

    M = simplify(R.T*Me*R)
    M_lumped = simplify(R.T*Me_lumped*R)

    print('printing M for code')
    for ind, val in np.ndenumerate(M):
        if val == 0:
            continue
        i, j = ind
        si = 'c1' if i < 3 else 'c2'
        sj = 'c1' if j < 3 else 'c2'
        print('        M[%d+%s, %d+%s]' % (i%3, si, j%3, sj), '+=', M[ind])

    print('printing M_lumped for code')
    for ind, val in np.ndenumerate(M_lumped):
        if val == 0:
            continue
        i, j = ind
        si = 'c1' if i < 3 else 'c2'
        sj = 'c1' if j < 3 else 'c2'
        print('        M[%d+%s, %d+%s]' % (i%3, si, j%3, sj), '+=', M_lumped[ind])


import numpy as np

def generate_synthetic_arithmetic_dataset(arithmetic_op, min_value, max_value, sample_size, set_size, boundaries = None):
    """
    generates a dataset of integers for the synthetics arithmetic task

    :param arithmetic_op: the type of operation to perform on the sum of the two sub sections can be either :
    ["add" , "subtract", "multiply", "divide", "root", "square"]
    :param min_value: the minimum possible value of the generated integers
    :param max_value: the maximum possible value of the generated integers
    :param sample_size: the number of integers per sample
    :param set_size: the number of samples in the dataset
    :param boundaries: [Optional] an iterable of 4 integer indices in the following format :
    [start of 1st section, end of 1st section, start of 2nd section, end of 2nd section]
    if None, the boundaries are randomly generated.
    :return: the training dataset input, the training true outputs, the boundaries of the sub sections used
    """
    scaled_input_values = np.random.randint(min_value, max_value, (set_size, sample_size))

    if boundaries is None:
        boundaries = [np.random.randint(sample_size) for i in range(4)]
        boundaries[1] = np.random.randint(boundaries[0], sample_size)
        boundaries[3] = np.random.randint(boundaries[2], sample_size)
    else:
        if len(boundaries) != 4:
            raise ValueError("boundaries is expected to be a list of 4 elements but found {}".format(len(boundaries)))

    a = np.array([np.sum(sample[boundaries[0]:boundaries[1]]) for sample in scaled_input_values])
    b = np.array([np.sum(sample[boundaries[2]:boundaries[3]]) for sample in scaled_input_values])
    true_outputs = None
    if "add" in str.lower(arithmetic_op):
        true_outputs = a + b
    elif "sub" in str.lower(arithmetic_op):
        true_outputs = a - b
    elif "mult" in str.lower(arithmetic_op):
        true_outputs = a * b
    elif "div" in str.lower(arithmetic_op):
        true_outputs = a / b
    elif "square" == str.lower(arithmetic_op):
        true_outputs = a * a
    elif "root" in str.lower(arithmetic_op):
        true_outputs = np.sqrt(a)

    return scaled_input_values, true_outputs, boundaries


import numpy as np

np.random.seed(1234)

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

def d_log(x):
    return log(x) * (1 - log(x))

x = np.array([
    [0,0,0],
    [0,0,1],
    [0,1,1]
])

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

wx = np.random.randn()
wrec = np.random.randn()
number_of_epoch = 15000

lr_wx = 0.001
lr_wrec = 0.001

state = np.zeros((x.shape[0],x.shape[1] + 1))
grad_over_time = np.zeros((x.shape))

for iter in range(number_of_epoch):

    state_1_in  = state[:,0]*wrec + x[:,0]*wx
    state_1_out = log(state_1_in)
    state[:,1] = state_1_out

    state_2_in  = state[:,1]*wrec + x[:,1]*wx
    state_2_out = log(state_2_in)
    state[:,2] = state_2_out

    state_3_in  = state[:,2]*wrec + x[:,2]*wx
    state[:,3] = state_3_in

    cost = np.square(state[:,3] - np.squeeze(y)).sum() / len(x)

    if iter % 1000 == 0:
        print("Current iter : ", iter, " Current cost: ", cost)

    grad_over_time[:,2] = (state[:,3] - np.squeeze(y)) * (2/len(x))
    grad_over_time[:,1] = grad_over_time[:,2] * wrec  * d_log(state_2_in)
    grad_over_time[:,0] = grad_over_time[:,1] * wrec  * d_log(state_1_in)

    grad_wx = np.sum(grad_over_time[:,2]*x[:,2]+
                    grad_over_time[:,1]*x[:,1]+
                    grad_over_time[:,0]*x[:,0])

    grad_wrec = np.sum(grad_over_time[:,2]*state[:,2]+
                    grad_over_time[:,1]*state[:,1]+
                    grad_over_time[:,0]*state[:,0])

    wx = wx - lr_wx * grad_wx
    wrec = wrec - lr_wrec * grad_wrec

# 3. Final Output
state_1_in  = state[:,0]*wrec + x[:,0]*wx
state_1_out = log(state_1_in)
state[:,1] = state_1_out

state_2_in  = state[:,1]*wrec + x[:,1]*wx
state_2_out = log(state_2_in)
state[:,2] = state_2_out

state_3_in  = state[:,2]*wrec + x[:,2]*wx
state[:,3] = state_3_in

print("-----------\n")
print("Final output Raw: ",state_3_in)
print("Final output Rounded: ",np.round(state_3_in))
print("Ground Truth : ",y.T)
print("-----------\n")

#  --- end code ---


#! /usr/bin/env python

"""
File: adaptive_trapezint.py
Copyright (c) 2016 Austin Ayers
License: MIT

Course: PHYS227
Assignment: 3.8
Date: Feb 11, 2016
Email: ayers111@mail.chapman.edu
Name: Austin Ayers
Description: Adaptive trapezoidal rule that decides how many trapezoids to use in order to achieve a desierd accuracy
"""
import numpy as np

def II_derivative_max(f, a, b, n=654321):
    """
    Calculates the maximum of the second derivative using many points: 654,321 of them to find the max of those points.
    """
    delta = (b - a) / float(n)
    max = abs(II_derivative(f, a))
    for i in range(n):
        current = abs(II_derivative(f, a + delta * (i + 1)))
        if current > max:
            max = current
    return max

def II_derivative(f, x, h=1e-6):
    return (f(x - h) - 2 * f(x) + f(x + h)) / float(h**2)

def trapezint(f, a, b, n):
    """
    Function from excercise 3.6
    """
    h = (b-a) / float(n)
    sum = 0
    for i in range(int(n)):
        sum = sum + (1/2.0)*h*(f(a + h*i) + f(a + h*(i + 1)))
    return sum

def adaptive_trapezint(f, a, b, eps=1E-5):
    """
    Adaptive trapezoidal rule that decides how many trapezoids to use in order to achieve a desierd accuracy
    """
    h = np.sqrt(12*eps)*(((b-a)*II_derivative_max(f, a, b))**(-1/2.0))
    n = (b-a)/float(h)
    return (trapezint(f, a, b, n), n)

def outputInformation():
    """
    Outputs the information of the exact error and estimated n for each case of adaptive_trapezint(f, a, b, eps=1E-5)
    """
    cos1 = adaptive_trapezint(cos, 0, np.pi)
    sin1 = adaptive_trapezint(sin, 0, np.pi)
    sin2 = adaptive_trapezint(sin, 0, np.pi/2)

    error1 = abs(cos1[0]-0)
    error2 = abs(sin1[0]-2)
    error3 = abs(sin2[0]-1)

    print("Function\tError\t\t\tEstimated n")
    print("Cos [0,Pi]\t" + str(error1) + "\t" + str(cos1[1]))
    print("Sin [0,Pi]\t" + str(error2) + "\t" + str(sin1[1]))
    print("Sin [0,Pi/2]\t" + str(error3) + "\t" + str(sin1[1]))
def line(x):
    return 2*x + 2
def sin(x):
    return np.sin(x)
def cos(x):
    return np.cos(x)

def test_trap_rule():
    """
    Area of a triangle = 1/2*b*h = 8 for the line 2x+2 integrated from 0 to 2
    """
    print(abs(trapezint(line, 0, 2, 100)))
    assert (abs(trapezint(line, 0, 2, 100) - 8) < 1E-5)


'''
Assortativity measures the similarity of connections in the graph with respect to the node degree.

Associative mixing by degree can be quantified in a number of ways, one of them is to use the correlation coefficient.

Graphs that have only single edges between vertices tend in the absence of other biases to show disassortative mixing by degree because the number of edges that can fall between high-degree vertex pairs is limited. Since most networks are represented as simple graphs this implies that most should be disassortative.

'''

import networkx as nx

def calculate(network):
    try:
        n = nx.degree_assortativity_coefficient(network)
    except:
        n = 0
    return round(n,7)


"""
Module for computing vertical motion
characteristics for a projectile.
"""
def y(v0, t):
    """
    Compute vertical position at time t, given the initial vertical
    velocity v0. Assume negligible air resistance.
    """
    g = 9.81
    return v0*t - 0.5*g*t**2

def time_of_flight(v0):
    """
    Compute time in the air, given the initial vertical
    velocity v0. Assume negligible air resistance.
    """
    g = 9.81
    return 2*v0/g

def max_height(v0):
    """
    Compute maximum height reached, given the initial vertical
    velocity v0. Assume negligible air resistance.
    """
    g = 9.81
    return v0**2/(2*g)

def application():
    import numpy as np
    import matplotlib.pyplot as plt
    import sys

    print("""This program computes vertical motion characteristics for a
    projectile. Given the intial vertical velocity, it computes height
    (as it develops with time), maximum height reached, as well as time
    of flight.""")

    try:
        v_initial = float(input('Give the initial velocity: '))
    except:
        print('You must give a valid number!')
        sys.exit(1)

    H = max_height(v_initial)
    T = time_of_flight(v_initial)
    print('Maximum height: {:g} m, \nTime of flight: {:g} s'.format(H, T))

    # compute and plot position as function of time
    dt = 0.001
    # just pick a "small" time step
    N = int(T/dt)
    # number of time steps
    t = np.linspace(0, N*dt, N+1)
    position = y(v_initial, t)
    # compute all positions (over T)
    plt.plot(t, position, 'b--')
    plt.xlabel('Time (s)')
    plt.ylabel('Vertical position (m)')
    plt.show()
    return

if __name__ == '__main__':
    application()


#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Numerical differentiation."""

import numpy as np

from jpy.maths.matrix import tridiag

def make_stencil(n, i, i_, _i):
    """Create a tridiagonal stencil matrix of size n.
    Creates a matrix to dot with a vector for performing discrete spatial computations.
    i, i_ and _i are multipliers of the ith, i+1 and i-1 values of the vector respectively.
    e.g. to calculate an average at position i based on neighbouring values:
    >>> s = make_stencil(N, 0, 0.5, 0.5)
    >>> avg_v = np.dot(s, v)
    The stencil has periodic boundaries.

    Returns an nxn matrix.
    """
    m = tridiag(n, i, i_, _i)
    m[-1,0] = i_
    m[0,-1] = _i
    return m

def make_central_difference1(n, dx):
    """Returns a function dfdx that calculates the first derivative
    of a list of values discretised with n points of constant separation dx.
    >>> x = np.arange(0, 1, 0.01)
    >>> y = np.sin(2*np.pi*x)
    >>> dfdx = make_central_difference1(len(x), 0.01)
    >>> dfdx(y)  #=> ~ 2π cos(2πx)"""
    m = make_stencil(n, 0, 1, -1) / (2*dx)
    def dfdx(phi):
        return np.dot(m, phi)
    return dfdx

def make_central_difference2(n, dx):
    """Returns a function df2dx that calculates the second derivative
    of a list of values discretised with n points of constant separation dx.
    >>> x = np.arange(0, 1, 0.01)
    >>> y = np.sin(2*np.pi*x)
    >>> d2fdx = make_central_difference2(len(x), 0.01)
    >>> dfdx(y)  #=> ~ -4π² sin(2πx)"""
    m = make_stencil(n, -2, 1, 1) / (dx**2)
    def d2fdx(phi):
        return np.dot(m, phi)
    return d2fdx

if __name__ == '__main__':
    # test: plot sin(2pi x) and dy/dx = cos(2pi x) [normalised]
    import matplotlib.pyplot as plt
    X = 1.0
    dx = 0.01
    x = np.arange(0,X,dx)
    y = np.sin(2*np.pi*x/X)
    dfdx = make_central_difference1(len(x), dx)
    d2fdx = make_central_difference2(len(x), dx)
    plt.plot(x, y)
    plt.plot(x, dfdx(y) / (2*np.pi))
    plt.plot(x, d2fdx(y) / (4*np.pi*np.pi))
    plt.legend(['y=sin(x)','dy/dx','d2y/dx'])
    plt.show()


# compute primes up to max number using the Sieve algorithm
# https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
#

import sys
import math
from numpy import arange
from datetime import *

def print_usage(name):
    print('python3 {} <max_number>'.format(name))

def create_number_list(max: int):
    numbers = arange(1, max, 2)
    return numbers

def mark_multiples_of_prime(numbers, prime_index: int, max: int):
    # print('Checking prime:{}'.format(prime))

    prime = numbers[prime_index]
    array_length = len(numbers)

    # the for loop will start at one multiple past the current prime
    # it will walk the list of numbers by multiples of prime
    # this logic removes the need for any if statements inside the loop
    for i in range(prime_index+prime, array_length, prime):
        numbers[i] = 0

def compute_primes(max: int):
    start_time = datetime.now()

    numbers = create_number_list(max)

    # print('Numbers = {}'.format(numbers))

    print('Computing primes from 0 to {}'.format(max))

    half_length = int(len(numbers)/2)

    for index in range(int(1), half_length):
        if (numbers[index] > 1):
            # print('index: {}, prime: {}'.format(index, numbers[index]))
            mark_multiples_of_prime(numbers, index, max)

    primes = [i for i in numbers if i>0]

    mid_time = datetime.now()

    # print('Primes = {}'.format(primes))

    finish_time = datetime.now()

    print('Start: {}, Mid: {}, Finish: {}'.format(start_time, mid_time, finish_time))
    print('Compute time: {}. \nFound {} prime numbers less than {}'.format(mid_time - start_time, len(primes), max))
    # print('Print time: {}'.format(finish_time - mid_time))

def main():
    if (len(sys.argv) > 1):
        compute_primes(int(sys.argv[1]))
    else:
        print_usage(sys.argv[0])

if __name__ == "__main__":
    main()


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

def convereged(new_mu, old_mu):
    return np.all(np.sort(new_mu) == np.sort(old_mu))

def recalculate_mu(clusters):
    mu = np.zeros(shape=(len(clusters.keys()), len(clusters.values()[0][0])))
    for k, points in clusters.items():
        if len(points) > 0:
            mu[k] = np.mean(points, axis=0)
    return mu

def calculate_center(data, mu, k):
    clusters = {i:[] for i in range(k)}
    for point in data:
        min_distance = sys.maxint
        best_k = 0
        for i, _muk in enumerate(mu):
            distance = np.linalg.norm(point - _muk)**2
            if distance < min_distance:
                min_distance = distance
                best_k = i
        clusters[best_k].append(point)
    new_mu = recalculate_mu(clusters)
    return new_mu, clusters

def k_means(data, k, label="", plot="False"):
    old_mu = np.array(random.sample(data, k))
    new_mu, clusters = calculate_center(data, old_mu, k)
    while not convereged(old_mu, new_mu):
        old_mu = new_mu
        new_mu, clusters = calculate_center(data, old_mu, k)
    if plot:
        colors = ['r', 'g', 'b', 'y', 'c']

        for k, points in clusters.items():
            np_points = np.array(points)
            plt.scatter(np_points[:, 0], np_points[:, 1], color=colors[k])
            plt.scatter(new_mu[k][0], new_mu[k][1], marker="^", color=colors[k], edgecolors='black', lw=1, s=50)
        plt.savefig("./images/{}-{}.png".format(label, k + 1))
        plt.close()

    return new_mu, clusters


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

import os
import sys
import numpy as np

def get_positive_y_max(b_bar, y):
    assert(len(b_bar) == len(y))

    j_min_ = None
    theta = float('inf')

    for i, (b_, y_) in enumerate(zip(b_bar, y)):
        if y_ <= 0.0:
            continue
        tmp = b_/y_
        if theta > tmp:
            theta = tmp
            j_min_ = i
    return j_min_, theta

if __name__ == '__main__':
    A = np.asarray([[1.0, 0.0, 1.0, 0.0, 0.0, 0.0],
                    [0.0, 1.0, 0.0, 1.0, 0.0, 0.0],
                    [1.0, -1.0, 0.0, 0.0, 1.0, 0.0],
                    [2.0, -1.0, 0.0, 0.0, 0.0, -1.0]])

    b = np.asarray([2.0, 3.0, 1.0, -1.0])
    c = np.asarray([-1.0, -2.0, 0.0, 0.0, 0.0, 0.0]) # need 0.0

    # initial index (they must be feasible...)
    B_index = np.asarray([2, 3, 4, 5])
    N_index = np.asarray([0, 1])

    # initial feasible solution
    B = A[:, B_index]
    B_inverse = np.linalg.inv(B)
    b_bar = np.dot(B_inverse, b)
    x = np.zeros(len(c), dtype = float)
    for x_, idx in zip(b_bar, B_index):
        x[idx] = x_

    # simplex loop
    while(True):
        c_B = c[B_index]
        c_N = c[N_index]
        B = A[:, B_index]
        N = A[:, N_index]
        B_inverse = np.linalg.inv(B)

        # pricing
        tmp = np.dot(B_inverse.transpose(), c_B)
        rho = c_N - np.dot(N.transpose(), tmp)
        k_ = np.argmin(rho)
        k = N_index[k_]

        if rho[k_] >= 0.0:
            break

        # ratio test
        b_bar = np.dot(B_inverse, b)
        y = np.dot(B_inverse, A[:, k])
        j_min_, theta = get_positive_y_max(b_bar, y)
        j_min = B_index[j_min_]

        # pivot
        x[k] = theta
        for tmp, idx in zip(y, B_index):
            x[idx] -= tmp * theta
        print(x)
        B_index = np.insert(B_index[B_index != j_min], 0, k)
        N_index = np.insert(N_index[N_index != k], 0, j_min)

    print(x)
    print('obj = {}'.format(np.dot(x, c)))


from __future__ import division
import numpy as np
import pylab as pl
import random
import math
import matplotlib.pyplot as plt
import matplotlib as mpl

'''
# plot sigmoid function
x = np.arange(-10,10,0.001)
# sigmoid = [i*i for i in x]
sigmoid = 1. / ( 1 + np.exp(-x) )
den = pow((1 + np.exp(-x)),2)
sigmoidDer = np.exp(-x) / ( den  )

fig = pl.figure()
pl.grid(True)
pl.xlim(-10, 10)
pl.ylim(-1, 1)
# pl.title('Sigmoid')
pl.plot(x, sigmoid, 'r-', label='Sigmoid function')
pl.plot(x, sigmoidDer, 'b--', label='Derivative of sigmoid function')
pl.legend()
# pl.xlabel('')
# pl.ylabel(u"sf")
pl.show()
fig.savefig('sigmoid.png')

'''

'''
# plot tanh function
x = np.arange(-10,10,0.001)
# sigmoid = [i*i for i in x]
tanh = (np.exp(x) - np.exp(-x)) / ( np.exp(x) + np.exp(-x) )
tanhDer = 1 - pow(tanh,2)

fig = pl.figure()
pl.grid(True)
pl.xlim(-10, 10)
pl.ylim(-1, 1)
# pl.title('Sigmoid')
pl.plot(x, tanh, 'r-', label='tanh function')
pl.plot(x, tanhDer, 'b--', label='Derivative of tanh function')
pl.legend()
# pl.xlabel('')
# pl.ylabel(u"sf")
pl.show()
fig.savefig('tanh.png')

'''

'''
# plot ReLU function
x = np.arange(-10,10,0.001)
# sigmoid = [i*i for i in x]
relu = np.where(x<0,0,x)
reluDer = np.where(x<0,0,1)

fig = pl.figure()
pl.grid(True)
pl.xlim(-2, 2)
pl.ylim(-2, 2)

pl.spines['top'].set_color('none')

# pl.title('Sigmoid')
pl.plot(x, relu, 'r-', label='ReLU function')
pl.plot(x, reluDer, 'b--', label='Derivative of ReLU function')
pl.legend()
# pl.xlabel('')
# pl.ylabel(u"sf")
pl.show()
fig.savefig('relu.png')
'''

'''
mpl.rcParams['axes.unicode_minus']=False

fig = plt.figure(figsize=(6,4))
ax = fig.add_subplot(111)

x = np.arange(-10, 10)
y = np.where(x<0,0,x)

plt.xlim(-11,11)
plt.ylim(-11,11)

ax.spines['top'].set_color('none')
ax.spines['right'].set_color('none')

ax.xaxis.set_ticks_position('bottom')
ax.spines['bottom'].set_position(('data',0))
ax.set_xticks([-10,-5,0,5,10])
ax.yaxis.set_ticks_position('left')
ax.spines['left'].set_position(('data',0))
ax.set_yticks([-10,-5,5,10])

plt.plot(x,y,label="ReLU",color = "red")
plt.legend()
plt.show()
fig.savefig('relu.png')

'''

'''
# plot leak ReLU function
mpl.rcParams['axes.unicode_minus']=False

fig = plt.figure(figsize=(6,4))
ax = fig.add_subplot(111)

x = np.arange(-10, 10)
y = np.where(x<0,0.2*x,x)

plt.xlim(-11,11)
plt.ylim(-11,11)

ax.spines['top'].set_color('none')
ax.spines['right'].set_color('none')

ax.xaxis.set_ticks_position('bottom')
ax.spines['bottom'].set_position(('data',0))
ax.set_xticks([-10,-5,0,5,10])
ax.yaxis.set_ticks_position('left')
ax.spines['left'].set_position(('data',0))
ax.set_yticks([-10,-5,5,10])

plt.plot(x,y,label="Leak ReLU",color = "red")
plt.legend()
plt.show()
fig.savefig('leakRelu.png')

'''

# plot ELU function
mpl.rcParams['axes.unicode_minus']=False

fig = plt.figure(figsize=(6,4))
ax = fig.add_subplot(111)

x = np.arange(-10, 10)
y = np.where(x<0,1*(np.exp(x)-1),x)

plt.xlim(-11,11)
plt.ylim(-11,11)

ax.spines['top'].set_color('none')
ax.spines['right'].set_color('none')

ax.xaxis.set_ticks_position('bottom')
ax.spines['bottom'].set_position(('data',0))
ax.set_xticks([-10,-5,0,5,10])
ax.yaxis.set_ticks_position('left')
ax.spines['left'].set_position(('data',0))
ax.set_yticks([-10,-5,5,10])

plt.plot(x,y,label="ELU",color = "red")
plt.legend()
plt.show()
fig.savefig('ELU.png')


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

mu = 0 # mean
sigma = 1 # standard deviation
normal_sample = np.random.normal(mu, sigma, 15000)

# plot the histogram of the sample distribution
fig, ax = plt.subplots()
ax.hist(normal_sample, bins='auto', density=True, color='#c7ddf4', edgecolor='#000000', label='Random sample with normal distribution')

# probability density function
x = np.arange(-5,5, 0.01)
normal_pdf = norm.pdf(x, loc= mu, scale = sigma)
ax.plot(x, normal_pdf, color='#ff464a', linewidth=1.5, linestyle='--', label=r'Normal PDF with $\mu$=0 and 1$\sigma$=1')
ax.legend(title='Normal Distribution')
ax.set_xlabel('x')
ax.set_ylabel('Probability Density')
ax.set_xlim(-5,5)
ax.set_ylim(0,0.6)

# Descriptive statistics
aritmetic_mean = normal_sample.mean()
standard_deviation = normal_sample.std()

print('Sample mean equal to {:.4f}'.format(aritmetic_mean))
print('Sample standard deviation equal to {:.4f}'.format(standard_deviation))

'''
Output: (your results will be sighly different because of the pseudo-random nature of the distribution)
Sample mean equal to -0.0014
Sample standard deviation equal to 1.0014
'''


#!/usr/bin/python
"""
author  : Bhekimpilo Ndhlela
author  : 18998712
module  : Applied Mathematics(Numerical Methods) TW324
task    : computer assignment 05 question 5
since   : Friday-27-04-2018
"""

def gauss_legendre(n=5.0):
    X, C = gauss(5, [-1, 1])
    f = lambda x : exp(x) / sqrt(1 - x**2)
    return sum([f(float(x)) * float(c) for x, c in zip(X, C)])

def gauss_chebyshev(n=5.0):
    X = [cos(((2.0 * i - 1) * pi) / (2 * n)) for i in xrange(1, int(n + 1))]
    return (pi * (sum([exp(x) for x in X]))) / n

def abs_error(xc, x):
    return abs(float(xc) - float(x))

if __name__ == "__main__":
    from scipy import (integrate, special)
    from math import (sqrt, exp, cos, pi)
    from gauss import gauss

    exact_integral = integrate.quad(lambda x : exp(x)/sqrt(1-x**2),-1,1)[0]
    gauss_chebyshev, gause_legendre = gauss_chebyshev(), gauss_legendre()

    debug = True
    if debug == True:
        print("Debug Mode Status: <ON>")
        print("Exact Integral  = {:.20f}".format(float(exact_integral)))
        print("Gauss Chebyshev = {:.20f}".format(abs_error(gauss_chebyshev, exact_integral)))
        print("Gauss Legendre  = {:.20f}".format(abs_error(gause_legendre, exact_integral)))
else:
    from sys import exit
    exit("USAGE: python question1.py")


import collections
import numpy as np

def mackey_glass(sample_len=1000, tau=17, seed=None, n_samples = 1):
    '''
    mackey_glass(sample_len=1000, tau=17, seed = None, n_samples = 1) -> input
    Generate the Mackey Glass time-series. Parameters are:
        - sample_len: length of the time-series in timesteps. Default is 1000.
        - tau: delay of the MG - system. Commonly used values are tau=17 (mild
          chaos) and tau=30 (moderate chaos). Default is 17.
        - seed: to seed the random generator, can be used to generate the same
          timeseries at each invocation.
        - n_samples : number of samples to generate
    '''
    delta_t = 10
    history_len = tau * delta_t
    # Initial conditions for the history of the system
    timeseries = 1.2

    if seed is not None:
        np.random.seed(seed)

    samples = []

    for _ in range(n_samples):
        history = collections.deque(1.2 * np.ones(history_len) + 0.2 * \
                                    (np.random.rand(history_len) - 0.5))
        # Preallocate the array for the time-series
        inp = np.zeros((sample_len,1))

        for timestep in range(sample_len):
            for _ in range(delta_t):
                xtau = history.popleft()
                history.append(timeseries)
                timeseries = history[-1] + (0.2 * xtau / (1.0 + xtau ** 10) - \
                             0.1 * history[-1]) / delta_t
            inp[timestep] = timeseries

        # Squash timeseries through tanh
        inp = np.tanh(inp - 1)
        samples.append(inp)
    return samples

def mso(sample_len=1000, n_samples = 1):
    '''
    mso(sample_len=1000, n_samples = 1) -> input
    Generate the Multiple Sinewave Oscillator time-series, a sum of two sines
    with incommensurable periods. Parameters are:
        - sample_len: length of the time-series in timesteps
        - n_samples: number of samples to generate
    '''
    signals = []
    for _ in range(n_samples):
        phase = np.random.rand()
        x = np.atleast_2d(np.arange(sample_len)).T
        signals.append(np.sin(0.2 * x + phase) + np.sin(0.311 * x + phase))
    return signals

def lorentz(sample_len=1000, sigma=10, rho=28, beta=8 / 3, step=0.01):
    """This function generates a Lorentz time series of length sample_len,
    with standard parameters sigma, rho and beta.
    """

    x = np.zeros([sample_len])
    y = np.zeros([sample_len])
    z = np.zeros([sample_len])

    # Initial conditions taken from 'Chaos and Time Series Analysis', J. Sprott
    x[0] = 0;
    y[0] = -0.01;
    z[0] = 9;

    for t in range(sample_len - 1):
        x[t + 1] = x[t] + sigma * (y[t] - x[t]) * step
        y[t + 1] = y[t] + (x[t] * (rho - z[t]) - y[t]) * step
        z[t + 1] = z[t] + (x[t] * y[t] - beta * z[t]) * step

    x.shape += (1,)
    y.shape += (1,)
    z.shape += (1,)

    return np.concatenate((x, y, z), axis=1)


# coding=utf-8
#Simple matrix inversion example
#Translated to Python by Kyrre Ness Sjøbæk

import numpy, computationalLib, math

myLib = computationalLib.pylib(inputcheck=False, cpp=False)

A = numpy.array([[1,3,4],[3,4,6],[4,6,8]],numpy.double)
print "Initial matrix A:\n", A

#LU-decompose A
matr = A.copy()
(matr,index,d) = myLib.luDecomp(matr);
print "LU-decomposed matrix:\n", matr
print "Index array:\n", index
print "Parity:\n", d

#Invert A column-by-column:
Ainv = numpy.zeros((3,3),numpy.double)
for j in xrange(3):
    col = numpy.zeros(3)
    col[j] = 1;

    Ainv[:,j] = myLib.luBackSubst(matr,index,col)

print "Inverse of A:\n", Ainv

#Test matrix inversion: AxAinv should be identity
test = True
ZERO = 1.0E-10
identity = numpy.zeros((3,3),numpy.double)
for i in xrange(3):
    for j in xrange(3):
        #Calculate and evaluate each element in resulting matrix:
        sum = 0.0;
        for k in xrange(3):
            sum = sum + A[i,k]*Ainv[k,j];
        if (i != j) and (sum > ZERO):
            test = False;
        if (i == j) and (math.fabs(sum - 1) > ZERO):
            test = False
        identity[i,j] = sum;
print "A*Ainv:\n", identity
if test:
    print "Status: OK"
else:
    print "Status: FAILED!"


import numpy as np

class Matrix:

    def __init__(self, A, b):
        if A.shape[0] != b.shape[0]:
            raise Exception('matrix dimension error')
        self.A = A
        self.b = b
        self.B = None
        self.q = None
        self.xk = np.zeros(b.shape[0])

    def find_matrix(self):
        self.q = self.b / self.A.diagonal()
        self.B = self.A / (-1 * self.A.diagonal()[:, None])
        np.fill_diagonal(self.B, np.zeros(self.q.shape[0]))

    def simple_iteration_method(self):
        c = self.A.dot(self.xk) != self.b
        while c.all():
            self.xk = self.B.dot(self.xk) + self.q
            c = self.A.dot(self.xk) != self.b
        return self.xk

    def get_xk(self):
        self.find_matrix()
        return self.simple_iteration_method()

if __name__ == "__main__":
    # Матрица A(по условию квадратная на множестве рациональных чисел)
    A = np.array([[2.0, 0.5, 0.1], [1.0, 5.0, 0.7], [0.6, 1.01, 8.0]])
    # Вектор b(по условию на множестве рациональных чисел)
    b = np.array([3.0, 3.0, 1.5])
    matrix = Matrix(A, b)
    print(f'x* = {matrix.get_xk()}')


import numpy as np
import sys
from matplotlib import pyplot as plt
import math

def function(x):
  #compute the value at the given coordinate
  try:
    x1 = np.float(x[0])
    x2 = np.float(x[1])
  except:
    print("input must be 2-D numerical vector")
    sys.exit(1)
  part_1 = math.sqrt(0.5*(x1*x1 + x2*x2))
  part_2 = 0.5*(math.cos(2*np.pi*x1) + math.cos(2*np.pi*x2))
  value = math.exp(1) + 20 -20*math.exp(-0.2 * part_1) - math.exp(part_2)

  #compute the gradient at the given coordinate
  part_1 = math.sqrt(0.5*(x1*x1 + x2*x2))
  part_2 = 0.5*(math.cos(2*math.pi*x1) + math.cos(2*math.pi*x2))
  gradient = [0,0]
  if np.abs(part_1) > 1e-12:
    gradient = 2 / part_1 * np.exp(-0.2 * part_1) * np.asarray([x1,x2]) + math.exp(part_2) * math.pi * np.sin(2*math.pi*np.asarray([x1,x2]))

  return value, gradient

def ackley_function_range(x_range_array):
  #returns an array of values for the given x range of values
  value = np.empty([len(x_range_array[0])])
  for i in range(len(x_range_array[0])):

    #returns the point value of the given coordinate
    part_1 = -0.2*math.sqrt(0.5*(x_range_array[0][i]*x_range_array[0][i] + x_range_array[1][i]*x_range_array[1][i]))
    part_2 = 0.5*(math.cos(2*np.pi*x_range_array[0][i]) + math.cos(2*np.pi*x_range_array[1][i]))

    value_point = math.exp(1) + 20 -20*math.exp(part_1) - math.exp(part_2)
    value[i] = value_point
  #returning the value array
  return value

def plot_general(fig):
  #this function will plot a general ackley function just to view it.
  limit = 1000 #number of points
  #common lower and upper limits for both x1 and x2 are used
  lower_limit = -5
  upper_limit = 5
  #generating x1 and x2 values
  x = np.linspace(-5, 5, 100)
  y = np.linspace(-5, 5, 100)
  X, Y = np.meshgrid(x, y)
  Z = np.zeros((len(X),len(Y)))
  for i in range(len(X)):
    for j in range(len(Y)):
        Z[i,j], _ = function([X[i,j],Y[i,j]])
  #plotting the function
  plt.contour(X, Y, Z, label='Ackley Function')

  def plot_ackley(x1_range,x2_range):
    #This would be the input for the Function
    x_range_array = [x1_range,x2_range]
    #generate the z range
    z_range = ackley_function_range(x_range_array)
    #plotting the function
    fig = plt.figure()
    ax = fig.gca(projection='3d')
    ax.scatter(x1_range, x2_range, z_range, label='Ackley Function')
    return fig, ax


import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
data=pd.read_csv('brain_head.csv')
print(data.head())
print(data.describe())

X=data['Head Size(cm^3)'].values
Y=data['Brain Weight(grams)'].values

mean_x=np.mean(X)
mean_y=np.mean(Y)

n=len(X)

a=0
b=0

for i in range(n):
	a+=(X[i]-mean_x)*(Y[i]-mean_y)
	b+=(X[i]-mean_x)**2

b1=a/b
b0=mean_y -(b1*mean_x)

print(b1,b0)
#the predicted line will be y=b0 + b1*x

print("Predicted regression line: y=" + str(b0) + str(b1)+"x")

x_max = np.max(X) + 100
x_min = np.min(X) - 100

#calculating line values of x and y
x = np.linspace(x_min, x_max, 1000)
y = b0 + b1 * x

#plotting line
plt.plot(x, y, color='#00ff00', label='Linear Regression')

#plot the data point
plt.scatter(X, Y, color='#ff0000', label='Data Point')

# x-axis label
plt.xlabel('Head Size (cm^3)')

#y-axis label
plt.ylabel('Brain Weight (grams)')

rmse = 0
for i in range(n):
    y_pred=  b0 + b1* X[i]
    rmse += (Y[i] - y_pred) ** 2

rmse = np.sqrt(rmse/n)

print(rmse)

sumofsquares = 0
sumofresiduals = 0

for i in range(n) :
    y_pred = b0 + b1 * X[i]
    sumofsquares += (Y[i] - mean_y) ** 2
    sumofresiduals += (Y[i] - y_pred) **2

score  = 1 - (sumofresiduals/sumofsquares)

print(score)
plt.legend()
plt.show()


# illustrate automatic differentiation using jax
# https://github.com/google/jax
import numpy as onp # original numpy
import jax.numpy as np
from jax import grad, hessian

onp.random.seed(42)
D = 5
w = onp.random.randn(D) # jax handles RNG differently

x = onp.random.randn(D)
y = 0 # should be 0 or 1

def sigmoid(x): return 0.5 * (np.tanh(x / 2.) + 1)

#d/da sigmoid(a) = s(a) * (1-s(a))
deriv_sigmoid = lambda a: sigmoid(a) * (1-sigmoid(a))
deriv_sigmoid_jax = grad(sigmoid)
a0 = 1.5
assert np.isclose(deriv_sigmoid(a0), deriv_sigmoid_jax(a0))

# mu(w)=s(w'x), d/dw mu(w) = mu * (1-mu) .* x
def mu(w): return sigmoid(np.dot(w,x))
def deriv_mu(w): return mu(w) * (1-mu(w)) * x
deriv_mu_jax =  grad(mu)
assert np.allclose(deriv_mu(w), deriv_mu_jax(w))

# NLL(w) = -[y*log(mu) + (1-y)*log(1-mu)]
# d/dw NLL(w) = (mu-y)*x
def nll(w): return -(y*np.log(mu(w)) + (1-y)*np.log(1-mu(w)))
#def deriv_nll(w): return -(y*(1-mu(w))*x - (1-y)*mu(w)*x)
def deriv_nll(w): return (mu(w)-y)*x
deriv_nll_jax = grad(nll)
assert np.allclose(deriv_nll(w), deriv_nll_jax(w))

# Now do it for a batch of data

def predict(weights, inputs):
    return sigmoid(np.dot(inputs, weights))

def loss(weights, inputs, targets):
    preds = predict(weights, inputs)
    logprobs = np.log(preds) * targets + np.log(1 - preds) * (1 - targets)
    return -np.sum(logprobs)

N = 3
X = onp.random.randn(N, D)
y = onp.random.randint(0, 2, N)

from jax import vmap
from functools import partial

preds = vmap(partial(predict, w))(X)
preds2 = vmap(predict, in_axes=(None, 0))(w, X)
preds3 = [predict(w, x) for x in X]
preds4 = predict(w, X)
assert np.allclose(preds, preds2)
assert np.allclose(preds, preds3)
assert np.allclose(preds, preds4)

grad_fun = grad(loss)
grads = vmap(partial(grad_fun, w))(X,y)
assert grads.shape == (N,D)
grads2 = np.dot(np.diag(preds-y), X)
assert np.allclose(grads, grads2)

grad_sum = np.sum(grads, axis=0)
grad_sum2 = np.dot(np.ones((1,N)), grads)
assert np.allclose(grad_sum, grad_sum2)

# Now make things go fast
from jax import jit

grad_fun = jit(grad(loss))
grads = vmap(partial(grad_fun, w))(X,y)
assert np.allclose(grads, grads2)

# Logistic regression
H1 = hessian(loss)(w, X, y)
mu = predict(w, X)
S = np.diag(mu * (1-mu))
H2 = np.dot(np.dot(X.T, S), X)
assert np.allclose(H1, H2)


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

def print_mat(mat):

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

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

def get_convergent_vector(L, r_0, threshold=0.01):

    '''
    :param L: transition matrix
    :param r_0: initial vector
    :param threshold: parameter for convergence condition
    :return: convergent vector
    '''

    r_cur = r_0

    while True:

        r_next = np.matmul(L, r_cur)

        if la.norm(r_next - r_cur) < threshold:
            # check convergence condition is met or not
            break

        r_cur = r_next

    return r_cur

# -----------------------------------
def get_matrix_with_damping(matrix, damping=0.5):

    # get the size of matrix
    n, _ = matrix.shape

    return matrix * damping + ( 1 - damping ) * np.ones((n, n)) / n

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

tokens = input().split()
n, damping_factor = int( tokens[0] ), float( tokens[1] )

matrix = [ [ 0.0 for x in range(n)] for y in range(n) ]

for y in range(n):
    matrix[y] = [ *map( float, input().split() ) ]

# convert to numpy array
matrix = np.array(matrix)

matrix_with_damping = get_matrix_with_damping(matrix, damping=damping_factor)

r_0 = ( np.ones(n) / n) * 100

# compute pagerank
r_pagerank = get_convergent_vector(L=matrix_with_damping, r_0=r_0, threshold=0.01)

# output result
print_mat(r_pagerank)


"""
Reference from the book <<Machine learning in action>>

@author: Peter Harrington
"""

import numpy as np

class PCA(object):

    def __init__(self, dataMat, percent=0.99):
        """

        :param dataMat: 输入训练集
        :param percent: 特征值数量的占比
        """
        self.percent = percent
        self.dataMat = dataMat

    def _zeroMean(self, dataMat):
        """
        对样本矩阵进行零均值处理
        :param dataMat: 按列进行求均值，每一列代表一个特征值
        :return:
        """
        meanMat = np.mean(dataMat, axis=0)
        zeroMat = dataMat - meanMat

        return zeroMat, meanMat

    def _getTopNFeatures(self, eigVals):
        """
        找到出现概率最多的N个特征
        :param eigVals: 特征值
        :return:
        """
        descendOrder = np.sort(eigVals)[-1::-1]
        orderSum = np.sum(descendOrder)
        tmp = 0
        num = 0
        for i in descendOrder:
            tmp += i
            num += 1
            if tmp > orderSum * self.percent:
                return num

    def pcaImplement(self):
        zeroMat, meanMat = self._zeroMean(self.dataMat)
        #计算协方差矩阵
        covMat = np.cov(zeroMat, rowvar=0)
        eigVals, eigVects = np.linalg.eig(np.mat(covMat))
        topN = self._getTopNFeatures(eigVals)
        eigValIndice = np.argsort(eigVals)
        topN_eigValIndice = eigValIndice[-1:-(topN - 1):-1]
        topN_eigVect = eigVects[:, topN_eigValIndice]
        #构建低维的特征空间的数据
        lowDDataMat = zeroMat * topN_eigVect
        reconMat = np.multiply(lowDDataMat, topN_eigVect.T) + meanMat

        return reconMat, lowDDataMat

class LoadData(object):

    def __init__(self, filepath, delimt='\t'):
        self.filepath = filepath
        self.delimt = delimt

    def _loadDataSet(self, filepath, delimt):
        """
        加载数据
        :param filepath:文件的位置
        :param delimt:文件里面的分隔符
        :return:
        """
        file = open(filepath)
        stringArr = [line.strip().split(delimt) for line in file]
        dataArr = [map(float, str) for str in stringArr]

        return np.mat(dataArr)

    def replaceNanWithMean(self):
        """
        将数据为空的字段替换掉
        :return:
        """
        dataMat = self._loadDataSet(self.filepath, self.delimt)
        numFeat = dataMat.shape[1]
        for i in range(numFeat):
            meanVal = np.mean(dataMat[np.nonzero(~np.isnan(dataMat[:, i].A))[0], i])
            dataMat[np.nonzero(np.isnan(dataMat[:, i].A))[0], i] = meanVal
        return dataMat


# -*- coding: utf-8 -*-
import numpy as np

def linear_gd(X, Y, alpha=0.01, epsilon=1e-8, trace=True):
    m = len(X)
    _X = np.column_stack((np.ones(m), X))
    m, n = np.shape(_X)
    theta, sse2, cnt = np.ones(n), 0, 0
    Xt = _X.T
    while True:
        loss = np.dot(_X, theta) - Y
        sse = np.dot(loss.T, loss) / (2 * m)
        if abs(sse - sse2) < epsilon:
            break
        else:
            sse2 = sse

        if trace:
            print("[ Epoch {0} ] theta = {1}, loss = {2}, error = {3})".format(cnt, theta, loss, sse))

        gradient = np.dot(Xt, loss) / m
        theta -= alpha * gradient
        cnt += 1

    return theta


import numpy as np
import scipy

a = [1,2,3,4,5.]

# A trick when you want to flatten a matrix X of shape (a,b,c,d) to a matrix X_flatten of shape (b ∗∗ c ∗∗ d, a) is to use:
# X_flatten = X.reshape(X.shape[0], -1).T      # X.T is the transpose of X

q = np.random.randint(7, size=(2, 3, 4))

# GRADED FUNCTION: sigmoid
def sigmoid(z):
    """
    Compute the sigmoid of z

    Arguments:
    z -- A scalar or numpy array of any size.

    Return:
    s -- sigmoid(z)
    """

    ### START CODE HERE ### (≈ 1 line of code)
    s = 1 / (1 + np.e ** (-z))
    ### END CODE HERE ###

    return s

# GRADED FUNCTION: initialize_with_zeros
def initialize_with_zeros(dim):
    """
    This function creates a vector of zeros of shape (dim, 1) for w and initializes b to 0.

    Argument:
    dim -- size of the w vector we want (or number of parameters in this case)

    Returns:
    w -- initialized vector of shape (dim, 1)
    b -- initialized scalar (corresponds to the bias)
    """

    ### START CODE HERE ### (≈ 1 line of code)
    w = np.zeros(shape=(dim, 1))
    b = 0
    ### END CODE HERE ###

    assert (w.shape == (dim, 1))
    assert (isinstance(b, float) or isinstance(b, int))

    return w, b

# GRADED FUNCTION: propagate
def propagate(w, b, X, Y):
    """
    Implement the cost function and its gradient for the propagation explained above

    Arguments:
    w -- weights, a numpy array of size (num_px * num_px * 3, 1)
    b -- bias, a scalar
    X -- data of size (num_px * num_px * 3, number of examples)
    Y -- true "label" vector (containing 0 if non-cat, 1 if cat) of size (1, number of examples)

    Return:
    cost -- negative log-likelihood cost for logistic regression
    dw -- gradient of the loss with respect to w, thus same shape as w
    db -- gradient of the loss with respect to b, thus same shape as b

    Tips:
    - Write your code step by step for the propagation. np.log(), np.dot()
    """

    m = X.shape[1]

    # FORWARD PROPAGATION (FROM X TO COST)
    ### START CODE HERE ### (≈ 2 lines of code)
    A = sigmoid(np.dot(w.T, X) + b)  # compute activation
    cost = - np.mean(Y * np.log(A) + (1 - Y) * np.log(1 - A))  # compute cost
    ### END CODE HERE ###

    # BACKWARD PROPAGATION (TO FIND GRAD)
    ### START CODE HERE ### (≈ 2 lines of code)
    dw = (1 / m) * np.dot(X, (A - Y).T)
    db = np.mean(A - Y)
    ### END CODE HERE ###

    assert (dw.shape == w.shape)
    assert (db.dtype == float)
    cost = np.squeeze(cost)
    assert (cost.shape == ())

    grads = {"dw": dw,
             "db": db}

    return grads, cost


import numpy as np
from scipy.spatial import distance

def cayley_menger_analysis(vertices, d = 2):
    """
    Determines volume and circumradius for a tetrahedron given the vertices
    https://westy31.home.xs4all.nl/Circumsphere/ncircumsphere.htm#Coxeter
    """
    if d == 3:
        cm_matrix = np.array([[0, 1, 1, 1, 1], [1, 0, distance.sqeuclidean(vertices[0], vertices[1]),
                            distance.sqeuclidean(vertices[0], vertices[2]),
                            distance.sqeuclidean(vertices[0], vertices[3])],
                            [1, distance.sqeuclidean(vertices[1], vertices[0]), 0,
                            distance.sqeuclidean(vertices[1], vertices[2]),
                            distance.sqeuclidean(vertices[1], vertices[3])],
                            [1, distance.sqeuclidean(vertices[2], vertices[0]),
                            distance.sqeuclidean(vertices[2], vertices[1]), 0,
                            distance.sqeuclidean(vertices[2], vertices[3])],
                            [1, distance.sqeuclidean(vertices[3], vertices[0]),
                            distance.sqeuclidean(vertices[3], vertices[1]),
                            distance.sqeuclidean(vertices[3], vertices[2]), 0]])

        cm_inv = np.linalg.inv(cm_matrix)
        centroid = [(vertices[0, 0] + vertices[1, 0] + vertices[2, 0] + vertices[3, 0])/4, \
                    (vertices[0, 1] + vertices[1, 1] + vertices[2, 1] + vertices[3, 1])/4, \
                    (vertices[0, 2] + vertices[1, 2] + vertices[2, 2] + vertices[3, 2])/4]
        v_simplex = np.sqrt(np.divide(np.linalg.det(cm_matrix), 288))
        r_simplex = np.sqrt(cm_inv[0,0]/-2)

    if d == 2:
        cm_matrix = np.array([[0, 1, 1, 1], [1, 0, distance.sqeuclidean(vertices[0], vertices[1]),
                            distance.sqeuclidean(vertices[0], vertices[2])],
                            [1, distance.sqeuclidean(vertices[1], vertices[0]), 0,
                            distance.sqeuclidean(vertices[1], vertices[2])],
                            [1, distance.sqeuclidean(vertices[2], vertices[0]),
                            distance.sqeuclidean(vertices[2], vertices[1]), 0]])

        cm_inv = np.linalg.inv(cm_matrix)
        centroid = [(vertices[0, 0] + vertices[1, 0] + vertices[2, 0])/3, (vertices[0, 1] + vertices[1, 1] + vertices[2, 1])/3]
        v_simplex = np.sqrt(np.divide(np.linalg.det(cm_matrix), -16))
        r_simplex = np.sqrt(cm_inv[0,0]/-2)

    return v_simplex, r_simplex, cm_inv[1::], centroid

def get_simplex_properties(tri, d = 2):

    if d == 2:
        area = []
        circumradius = []
        circumcenter = []
        centroid = []
        for i in tri.simplices:
            a, r, center, centr = cayley_menger_analysis(tri.points[i], d = d)
            area.append(a)
            circumradius.append(r)
            circumcenter.append(center)
            centroid.append(centr)

        return np.array(area), np.array(circumradius), np.array(circumcenter), np.array(centroid)

    if d == 3:
        volume = []
        circumradius = []
        circumcenter = []
        centroid = []
        for i in tri.simplices:
            a, r, center, centr = cayley_menger_analysis(tri.points[i], d = d)
            volume.append(a)
            circumradius.append(r)
            circumcenter.append(center)
            centroid.append(centr)

        return np.array(volume), np.array(circumradius), np.array(circumcenter), np.array(centroid)


# Para visualizar gráficos en la terminal interactiva
from IPython import get_ipython
get_ipython().run_line_magic('matplotlib', 'ipympl')

"""
# Actividad en clases: Aliasing

Objetivos:

- Reconstruir señales usando los resultados del teorema del muestreo
- Estudiar de forma práctica el fenomeno de aliasing

Para esta actividad consideremos la siguiente señal periódica con componentes 1Hz, 12Hz y 23Hz, respectivamente

"""

import numpy as np
import scipy.fft
import matplotlib.pyplot as plt

Fs = 1000
tn = np.arange(0, 2, step=1/Fs)
sn = np.cos(2.0*np.pi*tn) + 0.5*np.cos(2.0*np.pi*tn*12) + 0.25*np.cos(2.0*np.pi*tn*23)
S = scipy.fft.rfft(sn)
f = scipy.fft.rfftfreq(n=len(tn), d=1/Fs)

fig, ax = plt.subplots(2, 1, figsize=(5, 3), tight_layout=True)
ax[0].plot(tn, sn, '.', markersize=1)
ax[1].plot(f, np.abs(S))

"""

Primero visualice la señal y el espectro de amplitud para Fs=1000, Fs=50, Fs=10. ¿En qué casos se pueden detectar sin ambiguedad las frecuencias de la señal?

"""

"""
El teorema del muestreo dice que una señal digital sn cuya frecuencia máxima sea menor que la mitad de la frecuencia de muestreo Fs puede reconstruirse sin perdidas usando la fórmula de interpolación indicada en https://phuijse.github.io/UACH-INFO183/lectures/unit1/lecture4.html#teorema-del-muestreo

que usando NumPy sería

s = np.sum(sn*np.sinc(Fs*(t-tn)))

Utilice la formula para reconstruir la señal usando una frecuencia de muestreo arbitrariamente alta (Fs = 10000) y discuta sobre lo que observa

"""


import numpy as np

# First 20 countries with employment data
countries = np.array([
    'Afghanistan', 'Albania', 'Algeria', 'Angola', 'Argentina',
    'Armenia', 'Australia', 'Austria', 'Azerbaijan', 'Bahamas',
    'Bahrain', 'Bangladesh', 'Barbados', 'Belarus', 'Belgium',
    'Belize', 'Benin', 'Bhutan', 'Bolivia',
    'Bosnia and Herzegovina'
])

# Employment data in 2007 for those 20 countries
employment = np.array([
    55.70000076,  51.40000153,  50.5       ,  75.69999695,
    58.40000153,  40.09999847,  61.5       ,  57.09999847,
    60.90000153,  66.59999847,  60.40000153,  68.09999847,
    66.90000153,  53.40000153,  48.59999847,  56.79999924,
    71.59999847,  58.40000153,  70.40000153,  41.20000076
])

# Change False to True for each block of code to see what it does

# Accessing elements
if False:
    print countries[0]
    print countries[3]

# Slicing
if False:
    print countries[0:3]
    print countries[:3]
    print countries[17:]
    print countries[:]

# Element types
if False:
    print countries.dtype
    print employment.dtype
    print np.array([0, 1, 2, 3]).dtype
    print np.array([1.0, 1.5, 2.0, 2.5]).dtype
    print np.array([True, False, True]).dtype
    print np.array(['AL', 'AK', 'AZ', 'AR', 'CA']).dtype

# Looping
if False:
    for country in countries:
        print 'Examining country {}'.format(country)

    for i in range(len(countries)):
        country = countries[i]
        country_employment = employment[i]
        print 'Country {} has employment {}'.format(country,
                country_employment)

# Numpy functions
if False:
    print employment.mean()
    print employment.std()
    print employment.max()
    print employment.sum()

def max_employment(countries, employment):
    '''
    Fill in this function to return the name of the country
    with the highest employment in the given employment
    data, and the employment in that country.
    '''
    max_country = None      # Replace this with your code
    max_value = None   # Replace this with your code

    return (max_country, max_value)


import numpy as np

# Forward kinematics.
# Calculation relies on cosine rule.

# Four-bar linkage solution process inspired by: https://www.youtube.com/watch?v=4O-XPJ7flLU&t=321s
# Animation source code inspiration: DIYwalkers.com

#####################################
# User input, two servo angles.

servo_angle_femur = -45 # degrees
servo_angle_tibia = 150  # degress

#####################################
# Frame parameters, set my physical model.
# Lower servo origin, tibia control.
Ax = -20
Ay = -20

# Upper servo origin, femur control.
Dx = 0
Dy = 0

# Link lengths
L2 = 23
L3 = 30
L4 = 23
L5 = 22
L6 = 23
L7 = 100
L8 = 100
L9 = 23
L10 = 100

#####################################
# Calculations
L1 = np.sqrt(np.square(Dx - Ax) + np.square(Dy - Ay))

theta1 = np.arcsin((Dy - Ay) / L1)
theta2 = np.radians(servo_angle_tibia)

AC = np.sqrt(np.square(L1) + np.square(L2) - 2 * L1 * L2 * np.cos(theta1 - theta2))
beta = np.arccos((np.square(L1) + np.square(AC) - np.square(L2)) / (2 * L1 * AC));
psi = np.arccos((np.square(L3) + np.square(AC) - np.square(L4)) / (2 * L3 * AC));
lamda = np.arccos((np.square(L4) + np.square(AC) - np.square(L3)) / (2 * L4 * AC));

theta3 = psi - beta + theta1;
theta4 = np.pi - lamda - beta + theta1;

Bx = Ax + L2 * np.cos(theta2)
By = Ay + L2 * np.sin(theta2)
Cx = Dx + L4 * np.cos(theta4)
Cy = Dy + L4 * np.sin(theta4)

kappa = np.arccos((np.square(L4) + np.square(L6) - np.square(L5)) / (2 * L4 * L6))

theta5 = np.radians(servo_angle_femur)
theta6 = theta4 - kappa

EG = np.sqrt(np.square(L6) + np.square(L8) - 2 * L6 * L8 * np.cos(theta6 - theta5))
mu = np.arccos((np.square(L8) + np.square(EG) - np.square(L6)) / (2 * L8 * EG));
omega = np.arccos((np.square(L7) + np.square(EG) - np.square(L9)) / (2 * L7 * EG));
rho = np.arccos((np.square(EG) + np.square(L9) - np.square(L7)) / (2 * EG * L9));

theta7 = mu - omega + theta5;
theta8 = np.pi - rho - mu + theta5;

Ex = Dx + L6 * np.cos(theta6)
Ey = Dy + L6 * np.sin(theta6)
Gx = Dx + L8 * np.cos(theta5)
Gy = Dy + L8 * np.sin(theta5)
Fx = Gx + L9 * np.cos(theta8)
Fy = Gy + L9 * np.sin(theta8)
Hx = Gx + L10 * np.cos(theta8 - np.pi)
Hy = Gy + L10 * np.sin(theta8 - np.pi)

#####################################
# Print results.

print("A = (%.2f, %.2f)" % (Ax, Ay))
print("B = (%.2f, %.2f)" % (Bx, By))
print("C = (%.2f, %.2f)" % (Cx, Cy))
print("D = (%.2f, %.2f)" % (Dx, Dy))
print("E = (%.2f, %.2f)" % (Ex, Ey))
print("F = (%.2f, %.2f)" % (Fx, Fy))
print("G = (%.2f, %.2f)" % (Gx, Gy))
print("H = (%.2f, %.2f)" % (Hx, Hy))

print("AC:", np.around(AC, 2))
print("EG:", np.around(EG, 2))

print("beta = %.2f" % (np.degrees(beta)))
print("psi = %.2f" % (np.degrees(psi)))
print("lamda = %.2f" % (np.degrees(lamda)))
print("kappa = %.2f" % (np.degrees(kappa)))
print("mu = %.2f" % (np.degrees(mu)))
print("omega = %.2f" % (np.degrees(omega)))
print("rho = %.2f" % (np.degrees(rho)))

print("theta1 = %.2f" % (np.degrees(theta1)))
print("theta2 = %.2f" % (np.degrees(theta2)))
print("theta3 = %.2f" % (np.degrees(theta3)))
print("theta4 = %.2f" % (np.degrees(theta4)))
print("theta5 = %.2f" % (np.degrees(theta5)))
print("theta6 = %.2f" % (np.degrees(theta6)))
print("theta7 = %.2f" % (np.degrees(theta7)))
print("theta8 = %.2f" % (np.degrees(theta8)))


# 1. Reebok is designing a new type of Crossfit shoe, the Nano X. The fixed cost for the
# production will be $24,000. The variable cost will be $36 per pair of shoes. The shoes will
# sell for $107 for each pair. Using Python, graph the cost and revenue functions and
# determine how many pairs of sneakers will have to be sold for the company to break even on
# this new line of shoes.

import matplotlib.pyplot as plt
import math

# Expenses
# y = 36x + 24000
exp_slope = 36
exp_int   = 24000

exp_x0 = 0
exp_y0 = exp_slope * exp_x0 + exp_int
exp_x1 = 1000
exp_y1 = exp_slope * exp_x1 + exp_int

# Revenue
# y = 107x
rev_slope = 107
rev_int   = 0

rev_x0 = 0
rev_y0 = rev_slope * rev_x0 + rev_int
rev_x1 = 1000
rev_y1 = rev_slope * rev_x1 + rev_int

# Breakeven
# 107x = 36x + 24000
#  71x = 24000
#    x = 338.028
#    y = 107(338.028) = 36169.014

be_x = 24000 / 71
be_y = 107 * be_x

# Plot the lines
fig, shoe = plt.subplots()
shoe.scatter([exp_x0, exp_x1],
             [exp_y0, exp_y1],
             c = 'r')
shoe.plot([exp_x0, exp_x1],
          [exp_y0, exp_y1],
          c = 'r', alpha = 0.3)

shoe.scatter([rev_x0, rev_x1],
             [rev_y0, rev_y1],
             c = 'g')
shoe.plot([rev_x0, rev_x1],
          [rev_y0, rev_y1],
          c = 'g', alpha = 0.3)

shoe.scatter([be_x],
             [be_y],
             c = 'b', s = 100)
plt.xlim(0, 750)
plt.ylim(0, 75000)
plt.show()

print("To break even, Reebok must sell",
      math.ceil(be_x), "shoes.")

# 2. Nicole invests a total of $17,500 in three products. She invests one part in a mutual fund
# which has an annual return of 11%. She invests the second part in government bonds at 7%
# per year. The third part she puts in CDs at 5% per year. She invests twice as much in the
# mutual fund as in the CDs. In the first year Nicole's investments bring a total return of $1495.
# How much did she invest in each product?

import numpy as np
from numpy.linalg import inv
import matplotlib.pyplot as plt
# x + y + z = 17500
# 0.11x + 0.07y + 0.05z = 1495
# x - 2z = 0

a = inv(np.matrix('1 1 1; 11 7 5; 1 0 -2'))
b = np.array([17500, 149500, 0])
res = a.dot(b)
print("mutual funds=", res[0, 0],
      "gov't bonds =", res[0, 1],
      "CDs         =", res[0, 2])

labels = 'Mut Funds', "Gov't Bonds", 'CDs'
sizes  =  [res[0, 0], res[0, 1], res[0, 2]]
colors = ['lightskyblue', 'pink', 'yellowgreen']

plt.pie(sizes, labels = labels, colors = colors,
        autopct = '%1.1f%%', startangle = 140)

plt.axis('equal')
plt.show()

# 3. A company has 252 sales reps, each to be assigned to one of four marketing teams. If the first
# team is to have three times as many members as the second team and the third team is to
# have twice as many members as the fourth team, how can the members be distributed among
# the teams?

import pandas as pd
# w + x + y + z = 252
# w = 3x
# y = 2z
# 3x + x + 2z + z = 252
# 4x + 3z = 252
# 4x = 252 - 3z
#  x = 63 - 3/4z
#  w = 3 * (63 - 3/4z)
#  w = 189 - 9/4z

res = []
for z in range(253):
    z = float(z)
    x = float(63 - 3 * z / 4)
    y = float(2 * z)
    w = float(189 - 9 * z / 4)
    a,b = False,False
    if (w > 0) & (x > 0) & (y > 0) & (z > 0):
        a = True
    if (w.is_integer()) & (x.is_integer()) & (y.is_integer()) & (z.is_integer()):
        b = True
    if a & b: res.append([w, x, y, z])

teams = ['team1', 'team2', 'team3', 'team4']
print(pd.DataFrame(res, columns = teams))
pd.DataFrame(res, columns = teams).plot(kind = 'bar', stacked = True)

# 4. A company makes three types of artisanal chocolate bars: cherry, almond, and raisin. Matrix
# A gives the amount of ingredients in one batch. Matrix B gives the costs of ingredients from
# suppliers J and K. Using Python, calculate the cost of 100 batches of each candy using
# ingredients from supplier K.

import numpy as np
a = np.matrix('6 8 1; 6 4 1; 5 7 1')
b = np.matrix('4 3; 4 5; 2 2')

batch = a.dot(b)
print("100 cherry =", batch[0, 1] * 100,
      "100 almond =", batch[1, 1] * 100,
      "100 raisin =", batch[2, 1] * 100)

# 5. Welsh-Ryan Arena seats 15,000 people. Courtside seats cost $8, first level seats cost $6, and
# upper deck seats cost $4. The total revenue for a sellout is $76,000. If half the courtside seats,
# half the upper deck seats, and all the first level seats are sold, then the total revenue is
# $44,000. How many of each type of seat are there?

import numpy as np
from numpy.linalg import inv
#  x +  y +  z = 15000
# 8x + 6y + 4z = 76000
# 0.5(8x + 4z) + 6y = 44000
# 4x + 6y + 2z = 44000

a = inv(np.matrix('1 1 1; 8 6 4; 4 6 2'))
b = np.array([15000, 76000, 44000])
res = a.dot(b)
print("courtside  =", res[0, 0],
      "first level=", res[0, 1],
      "upper deck =", res[0, 2])

# 6. Due to new environmental restrictions, a chemical company must use a new process to
# reduce pollution. The old process emits 6 g of Sulphur and 3 g of lead per liter of chemical
# made. The new process emits 2 g of Sulphur and 4 g of lead per liter of chemical made. The
# company makes a profit of 25¢ per liter under the old process and 16¢ per liter under the new
# process. No more than 18,000 g of Sulphur and no more than 12,000 g of lead can be emitted
# daily. How many liters of chemicals should be made daily under each process to maximize
# profits? What is the maximum profit?

from scipy.optimize import linprog as lp
import numpy as np
# maximize: 0.25x + 0.16y
# subject to:
#   6x + 2y <= 18000
#   3x + 4y <= 12000
#      x, y >= 0

A = np.array([[6,  2], [3, 4]])
b = np.array([18000, 12000])
liters = lp(np.array([-0.25, -0.16]), A, b)

print("old method=", round(liters.x[0], 2), "liters.",
      "new method=", round(liters.x[1], 2), "liters.")
print("Max daily profit=",
      round(0.25 * liters.x[0] + 0.16 * liters.x[1], 2))

# 7. Northwestern is looking to hire teachers and TA’s to fill its staffing needs for its summer
# program at minimum cost. The average monthly salary of a teacher is $2400 and the average
# monthly salary of a TA is $1100. The program can accommodate up to 45 staff members and
# needs at least 30 to run properly. They must have at least 10 TA’s and may have up to 3 TA’s
# for every 2 teachers. Using Python, find how many teachers and TA’s the program should
# hire to minimize costs. What is the minimum cost?

from scipy.optimize import linprog as lp
import numpy as np
# minimize: 2400x + 1100y
# subject to:
#   x + y <= 45
#   x + y >= 30
#       y >= 10
#      2y <= 3x
#    x, y >= 0

A = np.array([[-1, -1], [-3, 2]])
b = np.array([-30, 0])
x_bounds = (0,  45)
y_bounds = (10, 45)
hire = lp(np.array([2400, 1100]), A, b,
          bounds = (x_bounds, y_bounds))

print("Hire", hire.x[0], "teachers.",
      "Hire", hire.x[1], "TAs.")
print("Minimum cost=",
      2400 * hire.x[0] + 1100 * hire.x[1])

# 8. To be at his best as a teacher, Roger needs at least 10 units of vitamin A, 12 units of vitamin
# B, and 20 units of vitamin C per day. Pill #1 contains 4 units of A and 3 of B. Pill #2 contains
# 1 unit of A, 2 of B, and 4 of C. Pill #3 contains 10 units of A, 1 of B, and 5 of C. Pill #1 costs
# 6 cents, pill #2 costs 8 cents, and pill #3 costs 1 cent. How many of each pill must Roger take
# to minimize his cost, and what is that cost?

from scipy.optimize import linprog as lp
import numpy as np
# minimize: 0.06x + 0.08y + 0.01z
# subject to:
#   4x +  y + 10z >= 10
#   3x + 2y +   z >= 12
#        4y +  5z >= 20
#         x, y, z >= 0

A = np.array([[-4, -1, -10], [-3, -2, -1], [0, -4, -5]])
b = np.array([-10, -12, -20])
pills = lp(np.array([0.06, 0.08, 0.01]), A, b)

print("Pill #1=", pills.x[0],
      "Pill #2=", pills.x[1],
      "Pill #3=", pills.x[2],)
print("Minimum cost=",
      0.06 * pills.x[0] + 0.08 * pills.x[1] + 0.01 * pills.x[2])

# 9. An electronics store stocks high-end DVD players, surround sound systems, and televisions.
# They have limited storage space and can stock a maximum of 210 of these three machines.
# They know from past experience that they should stock twice as many DVD players as stereo
# systems and at least 30 television sets. If each DVD player sells for $450, each surround
# sound system sells for $2000, and each television sells for $750, how many of each should be
# stocked and sold for maximum revenues? What is the maximum revenue?

from scipy.optimize import linprog as lp
import numpy as np
# maximize: 450x + 2000y + 750z
# subject to:
#   x + y + z <= 210
#   x >= 2y
#   z >= 30
#   x, y, z >= 0

A = np.array([[1, 1, 1], [-1, 2, 0], [0, 0, -1]])
b = np.array([210, 0, -30])
units = lp(np.array([-450, -2000, -750]), A, b)

print("DVDs =", units.x[0],
      "SS Systems=", units.x[1],
      "TVs =", units.x[2],)
print("Maximum revenue=",
      450 * units.x[0] + 2000 * units.x[1] + 750 * units.x[2])

# 10. A fast-food company is conducting a sweepstakes, and ships two boxes of game pieces to a
# particular franchise. Box A has 4% of its contents being winners, while 5% of the contents of
# box B are winners. Box A contains 27% of the total tickets. The contents of both boxes are
# mixed in a drawer and a ticket is chosen at random. Using Python, find the probability it
# came from box A if it is a winner.

is_box_a  = 0.27
box_a_win = 0.04
box_b_win = 0.05

a = is_box_a * box_a_win
b = (1 - is_box_a) * box_b_win
prob = a / (a + b)

print("Probability that winner came from Box A is",
      round(prob * 100, 3), "%.")

# Heatmap of probabilities for drawing random card
import pandas as pd
import seaborn as sns

a2 = is_box_a * (1 - box_a_win)
b2 = (1 - is_box_a) * (1 - box_b_win)
prob2 = a  / (a + b + a2 + b2)
prob3 = b  / (a + b + a2 + b2)
prob4 = a2 / (a + b + a2 + b2)
prob5 = b2 / (a + b + a2 + b2)

df = pd.DataFrame([[prob2, prob4], [prob3, prob5]],
                  index = ['Box A', 'Box B'],
                  columns = ['Winner', 'Loser'])
sns.heatmap(df)


import pandas as pd
import numpy as np
from scipy.integrate import solve_ivp, odeint
import matplotlib.pyplot as plt

"""
Transmission rate = What percentage of contacts do you transmit the disease to?
Contact rate = Number of contacts per unit time. Here we can define "unit of time" as 1 day.

If TR = 30% and CR = 1 person per day, then beta = 0.3
Where Beta is effective contact rate

If A people recover or die every B days (unit of time), then removal rate is A/B.
However, the model does not take into account the population change due to deaths (or new births).
"""

# Function for simulating a simple SIR model which takes population,
def sir_simple(t, state, N, beta, gamma):
    #state is a shape(n,) array
    S, I, R = state
    dSdt = - (beta * I * S)/N
    dIdt = ((beta * I * S)/N) - (gamma * I)
    dRdt = gamma * I
    return dSdt, dIdt, dRdt

def sir_vitaldynamics(t, state, N, beta, gamma, death_rate, birth_rate):
    #state is a shape(n,) array
    S, I, R = state
    dSdt = birth_rate - (death_rate * S) - (beta * I * S)/N
    dIdt = ((beta * I * S)/N) - (gamma * I) - (death_rate * I)
    dRdt = (gamma * I) - (death_rate * R)
    return dSdt, dIdt, dRdt

if __name__ == '__main__':
    beta = 0.25 # 1/beta is the typical time between contacts
    gamma = 0.1 # 1/gamma is the typical time until removal

    #The R0 of the disease is beta/gamma = 0.3/0.1 = 3

    population = 1000
    removed = 0
    infected = 1
    susceptible = population - infected - removed
    time_eval = np.linspace(start=0, stop=365, num=365)
    time_span = (time_eval[0], time_eval[len(time_eval) - 1])

    death_rate = 0.004
    birth_rate = 0.005

    """Documentation: https://docs.scipy.org/doc/scipy/reference/generated/scipy.integrate.solve_ivp.html"""
    res = solve_ivp(fun=sir_simple, t_span=time_span, y0=[susceptible, infected, removed],
                    args=(population, beta, gamma), t_eval=time_eval)

    df_sir = pd.DataFrame({"time": res.t, "susceptible":res.y[0], "infected":res.y[1], "removed":res.y[2]})

    res2 = solve_ivp(fun=sir_vitaldynamics, t_span=time_span, y0=[susceptible, infected, removed],
                    args=(population, beta, gamma, death_rate, birth_rate), t_eval=time_eval)

    df_sir2 = pd.DataFrame({"time":res2.t, "susceptible":res2.y[0], "infected":res2.y[1], "removed":res.y[2]})

    #Plotting the pandemic
    plt.style.use('fivethirtyeight')
    df_sir2.plot(x='time')
    plt.show()


import numpy as np

class SimpleSolver:
    def __init__(self, A, b, N_idx, B_idx, C):
        self.A = A
        self.b = b
        self.N_idx = N_idx
        self.B_idx = B_idx
        self.C = C

        self.x_B = np.zeros(len(B_idx))
        self.x_N = np.zeros(len(N_idx))

    def solve(self, max_iter=100):
        optimal_solution = np.zeros(len(self.B_idx) + len(self.N_idx))

        for itr in range(max_iter):
            print("N_idx is ", [i + 1 for i in self.N_idx])
            print("B_idx is ", [i + 1 for i in self.B_idx])

            b_hat = np.linalg.inv(self.A[:, self.B_idx]).dot(self.b)
            print("b_hat is ", b_hat)

            c_hat_N = self.C[self.N_idx] - self.A[:, self.N_idx].T.dot(
                np.linalg.inv(self.A[:, self.B_idx]).T
            ).dot(self.C[self.B_idx])
            print("c_hat_N is", c_hat_N)
            if np.max(c_hat_N) <= 0:
                z = self.C[self.B_idx].T.dot(b_hat)
                optimal_solution[self.B_idx] = b_hat
                print("Done!")
                print("optimal z is ", z)
                print("optimal solution is ", optimal_solution)

                break

            k = np.where(c_hat_N > 0)[0][-1]

            a_hat_k = self.A[:, self.N_idx][:, k]
            print("a_hat_k", a_hat_k)
            if np.max(a_hat_k) <= 0:
                break

            temp_thetas = [b_hat[i] / a_ik for i, a_ik in enumerate(a_hat_k)]
            min_i = np.argmin(temp_thetas)
            theta = temp_thetas[min_i]

            self.x_N[k] = theta
            self.x_B = b_hat - theta * a_hat_k

            print(f"swap x_{self.B_idx[min_i]+1} ans x_{self.N_idx[k]+1}")
            temp_i = self.B_idx[min_i]
            temp_k = self.N_idx[k]
            self.B_idx[min_i] = temp_k
            self.N_idx[k] = temp_i

            temp_x_i = self.x_B[min_i]
            temp_x_k = self.x_N[k]
            self.x_B[min_i] = temp_x_k
            self.x_N[k] = temp_x_i
            print("x_B is ", self.x_B)
            print("x_N is ", self.x_N)

        return optimal_solution, z

if __name__ == "__main__":
    print("example")
    A = np.array([[1, 1, 1, 0, 0], [1, 3, 0, 1, 0], [2, 1, 0, 0, 1]])
    b = np.array([6, 12, 10])
    B_idx = [2, 3, 4]
    N_idx = [0, 1]
    C = np.array([1, 2, 0, 0, 0])
    simplexsolver = SimpleSolver(A, b, N_idx, B_idx, C)
    simplexsolver.solve()

    print("2.4.1")
    A = np.array([[1, 1, 1, 1, 0, 0], [3, 4, 6, 0, 1, 0], [4, 5, 3, 0, 0, 1]])
    b = np.array([20, 100, 100])
    B_idx = [3, 4, 5]
    N_idx = [0, 1, 2]
    C = np.array([4, 8, 10, 0, 0, 0])
    simplexsolver = SimpleSolver(A, b, N_idx, B_idx, C)
    simplexsolver.solve()

    print("2.4.3")
    A = np.array([[1, 0, 1, 0], [20, 1, 0, 1]])
    b = np.array([1, 100])
    B_idx = [2, 3]
    N_idx = [0, 1]
    C = np.array([10, 1, 0, 0])
    simplexsolver = SimpleSolver(A, b, N_idx, B_idx, C)
    simplexsolver.solve()


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

# Data
alpha = 0.05
true_mean = 79.3
true_std = 0.3
print(f'True mean: {true_mean} | True std {true_std}')

for i,n in enumerate([10,20,50,100]):
    x = np.random.normal(loc=true_mean, scale=true_std, size=n)

    ### Frequentist model - Confidence interval ###
    x_bar = np.sum(x)/n
    z = norm.ppf(1-alpha/2)
    freq_left = round(x_bar - z*true_std/np.sqrt(n), 3)
    freq_right = round(x_bar + z*true_std/np.sqrt(n), 3)
    print('')
    print(f'n = {str(n).zfill(3)} | 95% confidence interval for mean: ({freq_left}, {freq_right})')

    ### Bayesian model - Credible interval ###
    """
    References:
        * https://stats.stackexchange.com/questions/82292/example-of-real-life-use-of-bayesian-inference-on-mu-from-a-normal-distribu
        * Casella, G. (1985). An Introduction to Empirical Bayes Data Analysis. The American Statistician, 39(2), 83-87.
    """
    # prior distribution
    prior_mean = 75
    prior_std = 4

    tau = 1/true_std**2
    b = 1/prior_std
    x_bar = np.sum(x)/n

    # posterior distribution
    theta_mean = (prior_mean*b + x_bar*n*tau) / (b + n*tau)
    theta_std = np.sqrt(1 / (b + n*tau))
    z = norm.ppf(1-alpha/2)

    bayesian_left = round(theta_mean - z*theta_std/np.sqrt(n), 3)
    bayesian_right = round(theta_mean + z*theta_std/np.sqrt(n), 3)

    print(f'n = {str(n).zfill(3)} | 95% credible interval for mean: ({bayesian_left}, {bayesian_right})')

    ### Plot the results ###
    plt.subplot(2,2,i+1)
    plt.title(f'Analysis with {n} data points')
    x_ = np.linspace(true_mean - 5*true_std, true_mean + 5*true_std, 500)
    y_ = norm.pdf(x_, loc=true_mean, scale=true_std) # true normal distribution
    plt.plot(x_, y_, label='original data')
    plt.vlines(true_mean, min(y_), max(y_), colors='k', label='true mean', zorder=2)
    plt.hlines(0.005,freq_left, freq_right, color='r', label='frequentist interval')
    plt.hlines(0.007,bayesian_left, bayesian_right, color='y', label='bayesian interval')
    plt.legend(loc="lower right")
    plt.tight_layout()
plt.show() # display all the graphs


import numpy as np
import matplotlib.pyplot as plt
import chaotic_maps as cm

fig, axes = plt.subplots(2, 2)
cm.cobweb_plot(cm.sin_map(.7), .1, 50, domain=np.linspace(0, 1), ax=axes[0][0], ylabel=r'$x_{n+1}$')
cm.cobweb_plot(cm.sin_map(.8), .1, 10, domain=np.linspace(0, 1), ax=axes[0][1])
cm.cobweb_plot(cm.sin_map(.85), .1, 50, domain=np.linspace(0, 1), ax=axes[1][0], xlabel=r'$x_n$', ylabel=r'$x_{n+1}$')
cm.cobweb_plot(cm.sin_map(.9), .1, 150, domain=np.linspace(0, 1), ax=axes[1][1], xlabel=r'$x_n$')
axes[0][0].set_title(r'$\mu = 0.7$')
axes[0][1].set_title(r'$\mu = 0.8$')
axes[1][0].set_title(r'$\mu = 0.85$')
axes[1][1].set_title(r'$\mu = 0.9$')
plt.tight_layout()
plt.savefig("sin_cobwebs.png", dpi=300)

cm.bifurcation_and_lyapunov_plots(
   cm.sin_map,
   init=0.2,
   parameter_range=np.linspace(0.6, 1, num=10000),
   deriv_generator=cm.sin_map_deriv,
   y_points=500,
   xlabel=r"$\mu$",
   ylabel=r"$x$",
   file_name="sine.png",
)

fig, axes = plt.subplots(1,2, figsize=(12,5))

cm.bifurcation_plot(
    cm.gauss_map_family(alpha=5),
    init=0.1,
    parameter_range=np.linspace(-0.9, 1, 10000),
    y_points=500,
    xlabel=r"$\beta$",
    ylabel=r"$x$",
    set_title=r"$\alpha = 5$",
    ax=axes[0]
)

cm.bifurcation_plot(
    cm.gauss_map_family(alpha=6.5),
    init=0.1,
    parameter_range=np.linspace(-0.9, 1, 10000), #10000
    y_points=500,
    xlabel=r"$\beta$",
    ylabel=r"$x$",
    set_title=r"$\alpha = 6.5$",
    ax=axes[1]
)

plt.savefig("gauss.png", dpi=300)


import sys
import getopt
import numpy as np
import matplotlib.pyplot as plt
import math
import pywt
from scipy.fftpack import dct, idct
from PIL import Image

'''
References:
    https://sukhbinder.wordpress.com/2014/09/11/karhunen-loeve-
    transform-in-python/

    http://stackoverflow.com/questions/3680262/how-to-slice-a-2d-python-
    array-fails-with-typeerror-list-indices-must-be-int

    http://stackoverflow.com/questions/16856788/slice-2d-array-into-smaller
    -2d-arrays
'''

def KLT(array):

    val, vec = np.linalg.eig(np.cov(array))
    klt = np.dot(vec, array)
    return klt, vec, val

def load_image_as_array(imgFile):
	img = Image.open(imgFile)
	imgArray = np.asarray(img)

	return imgArray

def get_2d_list_slice(self, matrix, start_row, end_row, start_col, end_col):
    return [row[start_col:end_col] for row in matrix[start_row:end_row]]

"""
Return an array of shape (n, nrows, ncols) where
n * nrows * ncols = arr.size

If arr is a 2D array, the returned array should look like n subblocks with
each subblock preserving the "physical" layout of arr.
"""
def blockshaped(arr, nrows, ncols):
    h, w = arr.shape
    return (arr.reshape(h//nrows, nrows, -1, ncols)
               .swapaxes(1,2)
               .reshape(-1, nrows, ncols))

"""
Return an array of shape (h, w) where
h * w = arr.size

If arr is of shape (n, nrows, ncols), n sublocks of shape (nrows, ncols),
then the returned array preserves the "physical" layout of the sublocks.
"""
def unblockshaped(arr, h, w):
    n, nrows, ncols = arr.shape
    return (arr.reshape(h//nrows, -1, nrows, ncols)
               .swapaxes(1,2)
               .reshape(h, w))

def dct_loop(img_array, loop_times):
    i = 0

    for i in range(0, loop_times):
        # slice into 8x8 chunks
        blockArr = blockshaped(img_array, 8, 8)

        # run DCT on each chunk
        j = 0
        for j in range (0, 4096): # for all the 8x8 blocks
            blockArr[j] = dct(np.array(blockArr[j]), 2, norm='ortho')

        # reshape
        dct_arr = unblockshaped(blockArr, 512, 512)
        img_array = dct_arr

    return dct_arr

def idct_loop(img_array, loop_times):
    i = 0

    for i in range(0, loop_times):
        # slice into 8x8 chunks
        blockArr = blockshaped(img_array, 8, 8)

        # run DCT on each chunk
        j = 0
        for j in range (0, 4096):
            blockArr[j] = idct(np.array(blockArr[j]), 2, norm='ortho')

        # reshape
        dct_arr = unblockshaped(blockArr, 512, 512)
        img_array = dct_arr

    return dct_arr

def calculate_error(img1_arr, img2_arr):
    arr1 = img1_arr.ravel()
    arr2 = img2_arr.ravel()

    i = 0
    error = 0.0
    for i in range (0, 262144):
        error += math.exp(int(arr1[i]) - int(arr2[i]))
        error = error / 262144

    return error

def main(argv):
    inputFile = ""

    # load file with command line args
    try:
        opts, args = getopt.getopt(argv,"i:")
    except getopt.GetoptError:
        print("USAGE: python3 main.py -i <file>")
        sys.exit(2)

    for opt, arg in opts:
        if opt == "-i":
            inputFile = arg
        else:
            print("USAGE: python3 main.py -i <file>")
            sys.exit()

    if (inputFile is ""):
        print("USAGE: python3 main.py -i <file>")
        sys.exit()

    # load image as array
    print("Loading image...")
    imgArr = load_image_as_array(inputFile)
    print("    Image loaded!")
    print()

    # do klt
    print("Determining KLT values...")
    ktm, vect, val = KLT(imgArr);
    print("    Found KLT values!")
    print()

    # run it through DCT 8x8 at a time
    # 4096 8x8 blocks in 512 x 512 array
    # 64 blocks in row, col

    print("Printing image array...")
    print(imgArr)
    print("    Done!")
    print()

    print("Applying one-level DWT...")
    coeffs = pywt.dwt2(imgArr, 'haar')
    cA, (cH, cV, cD) = coeffs
    print("    Done!")

    dwtCompList = [cA, cH, cV, cD]
    stitchArr = unblockshaped(np.array(dwtCompList), 512, 512)

    print("Displaying image...")
    #pass1 = Image.fromarray(stitchArr, 'L')
    pass1 = Image.fromarray(stitchArr)
    pass1.show()
    #pass1.save('DWT2D_transform.spi', format='SPIDER')
    print("    Done!")

    print("Applying inverse transform and displaying image...")
    finalArr = np.array((pywt.idwt2(coeffs, 'haar')), dtype=np.uint8)
    pass2 = Image.fromarray(finalArr)
    pass2.save('iDWT2D_reconstruction.bmp')
    print("    Done!")
    print()

    '''
    Calculate the error between the two images
    '''
    print("Calculating error between the original image and final...")
    imgError = calculate_error(np.asarray(imgArr), np.asarray(finalArr))
    print ("Mean squared error: ""{:.12}%".format(float(imgError * 100)))

if __name__ == "__main__":
	main(sys.argv[1:])


import numpy as np
def unitStep(v):
    if v>=0:
        return 1
    else:
        return 0

def perceptronModel(x,w,b):
     v = np.dot(w,x)+b
     y= unitStep(v)
     return y

def OR_logicfunction(x):
     w = np.array([0.5,0.5])
     b = -0.3
     return perceptronModel(x,w,b)

test1 = np.array([0, 0])
test2 = np.array([0, 1])
test3 = np.array([1, 0])
test4 = np.array([1, 1])

print("OR({},{}) = {}".format(0, 0,OR_logicfunction(test1)))
print("OR({},{}) = {}".format(0, 1, OR_logicfunction(test2)))
print("OR({},{}) = {}".format(1, 0, OR_logicfunction(test3)))
print("OR({},{}) = {}".format(1, 1, OR_logicfunction(test4)))


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

Xvet = np.array([8,12], dtype=np.float)
Fvet = np.array([ 0.9030900,1.0791812], dtype=np.float)

def polinom(coefs,x):
    resultado = 0
    for i in range(0,len(coefs)):
        resultado = resultado + coefs[i]*math.pow(x,i)

    return resultado

def Interpol(xs, fs):
    M = np.zeros((len(xs),len(xs)), dtype=np.float)
    Y = fs.copy()

    for j in range(0,len(xs)):
        for i in range(0,len(xs)):
            M[i][j] = math.pow(xs[i],j)

    coefs = ElimGauss(M,Y)
    return coefs

def ElimGauss(matriz, coef):
    A = matriz.copy()
    b = coef.copy()

    for i in range(0, len(coef)):
        for j in range(0, len(coef)):
            if ( i != j) :
                fator = A[j][i]/A[i][i]
                b[j] = b[j] -fator*b[i]
                for k in range(0,len(coef)):
                    A[j][k] = A[j][k] - fator*A[i][k]

    for i in range(0,len(coef)):
        b[i] = b[i] / A[i][i]
        A[i][i] = 1

    return b

coefs = Interpol( Xvet, Fvet)
#print(coefs)
x = 10
y = polinom(coefs,x)
print("O valor do polinômio interpolador no ponto "+str(x)+" eh "+str(y))
erro = abs( math.log( x, 10) - y  )/abs(math.log( x, 10) )
print("O erro relativo eh "+str(erro*100)+"%")