#!/usr/bin/env python3
import sys
from mpi4py import MPI
import numpy as np

np.random.seed(2017)

comm = MPI.COMM_WORLD
size = comm.Get_size()
rank = comm.Get_rank()

def inside_circle(total_count):

    hname = MPI.Get_processor_name()

    x = np.float32(np.random.uniform(size=total_count))
    y = np.float32(np.random.uniform(size=total_count))

    radii = np.sqrt(x*x + y*y)

    count = len(radii[np.where(radii<=1.0)])

    return count

def estimate_pi(n_samples):

    counts = inside_circle(n_samples)
    return (4.0 * sum(counts) / total_count)

if __name__=='__main__':

    n_samples = 10000
    if len(sys.argv) > 1:
        n_samples = int(sys.argv[1])

    if rank == 0:
        partitions = [ int(n_samples/size) for item in range(size)]
        counts = [ int(0) ] *size
    else:
        partitions = None
        counts = None

    partition_item = comm.scatter(partitions, root=0)
    count_item = comm.scatter(counts, root=0)

    count_item = inside_circle(partition_item)

    counts = comm.gather(count_item, root=0)
    if rank == 0:
        my_pi = 4.0 * sum(counts) / n_samples
        sizeof = np.dtype(np.float32).itemsize
        print("[     mpi version] required memory %.3f MB" % (n_samples*sizeof*3/(1024*1024)))
        print("[using %3i cores ] pi is %f from %i samples" % (size,my_pi,n_samples))


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

# Define some test data which is close to Gaussian
data = numpy.random.normal(size=10000)

hist, bin_edges = numpy.histogram(data, density=True)
bin_centres = (bin_edges[:-1] + bin_edges[1:])/2

# Define model function to be used to fit to the data above:
def gauss(x, *p):
    A, mu, sigma = p
    return A*numpy.exp(-(x-mu)**2/(2.*sigma**2))

# p0 is the initial guess for the fitting coefficients (A, mu and sigma above)
p0 = [1., 0., 1.]

coeff, var_matrix = curve_fit(gauss, bin_centres, hist, p0=p0)

# Get the fitted curve
hist_fit = gauss(bin_centres, *coeff)

plt.plot(bin_centres, hist, label='Test data')
plt.plot(bin_centres, hist_fit, label='Fitted data')

# Finally, lets get the fitting parameters, i.e. the mean and standard deviation:
print 'Fitted mean = ', coeff[1]
print 'Fitted standard deviation = ', coeff[2]

plt.show()


import numpy as np

# Create numpy arrays, list and change elements

a=np.array([1,2,3]) # create a 1D array
print('Dimensions of the array = ',a.ndim) # print the dimensions of the array
print('Shape of the array = ', a.shape) # print the shape of the array
a=np.array([ [1,2,3] ])
print('Dimensions of the array = ', a.ndim) # print the dimensions of the array
print('Shape of the array = ', a.shape) # print the shape of the array

b = np.array([[1,2,3],[4,5,6]])   # Create a rank 2 array
print('Shape of the array = ',b.shape)                     # Prints "(2, 3)"
print('Print select elements of b array')
print(b[0, 0], b[0, 1], b[1, 0])   # Prints "1 2 4"
print(b[0][0], b[0][1], b[0][1])   # Prints "1 2 4"
print('Modify array elements in location 0,2')
b[0,2]=999
print('New value in b[0,2] = ', b[0,2])  # [[  1   2   3]
 				         # [  4   5 999]]
print('New b array = ')
print(b)
print()
print('Create an array of zeros')
a = np.zeros((2,2))  # Create an array of all zeros
print(a)             # Prints "[[ 0.  0.]
                     #          [ 0.  0.]]"

print()
print('Create an array of ones')
b = np.ones((1,2))   # Create an array of all ones
print(b)             # Prints "[[ 1.  1.]]"
print()
print('Create an identity matrix')
d = np.eye(2)        # Create a 2x2 identity matrix
print(d)              # Prints "[[ 1.  0.]
                     #          [ 0.  1.]]"
print()
print('Create a random 2x2 array')
e = np.random.random((2,2)) # Create an array filled with random values
print(e)                     # Might print "[[ 0.91940167  0.08143941]
                            #               [ 0.68744134  0.87236687]]"
print()
print('Create a 1D random integer array between 10-100')
e = np.random.random_integers(10,100,10) # print 10 random integers between 10 to 100
print(e)
print()
print('Create a 10x10 random integer array between 10-100')
e = np.random.random_integers(10,100,(10,10)) # print 100 random integers and place them in 10x10 array
print(e)
print()
wait = input("PRESS ENTER TO CONTINUE.")

#Slicing: Numpy arrays can be sliced. Since arrays may be multidimensional, you must specify a slice for each dimension of the array:

print('Create a 3x4 array')
a = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])
print(a)
# [[ 1  2  3  4]
#  [ 5  6  7  8]
#  [ 9 10 11 12]]
print()
print('Pull out subarray first 2 rows and columns 1-2')
# Use slicing to pull out the subarray consisting of the first 2 rows
# and columns 1 and 2; b is the following array of shape (2, 2):
b = a[:2, 1:3] # [[2 3]
               #  [6 7]]
print(b)
print()

# Modifying a slice of an array modifies the original array
print('Modify a slice and compare to the original array')
print('Value of element 0,1 of a is',a[0, 1])   # Prints "2"
print('Modify 0,0 of array b to value 77')
b[0, 0] = 77    # b[0, 0] is the same piece of data as a[0, 1]
print('Value of element 0,1 of a is now ',a[0, 1])   # Prints "77"
print()

# Create the following rank 2 array with shape (3, 4)
# [[ 1  2  3  4]
#  [ 5  6  7  8]
#  [ 9 10 11 12]]
a = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])
print()

wait = input("PRESS ENTER TO CONTINUE.")

# Two ways of accessing the data in the middle row of the array.
# Mixing integer indexing with slices yields an array of lower rank,
# while using only slices yields an array of the same rank as the
# original array:
row_r1 = a[1, :]    # Rank 1 view of the second row of a
row_r2 = a[1:2, :]  # Rank 2 view of the second row of a
print('Print extracted row, shape and dims = ',row_r1, row_r1.shape,row_r1.ndim)  # Prints "[5 6 7 8] (4,) 1"
print('Print extracted row, shape and dims = ',row_r2, row_r2.shape,row_r2.ndim)  # Prints "[[5 6 7 8]] (1, 4) 2"

# We can make the same distinction when accessing columns of an array:
col_r1 = a[:, 1]
col_r2 = a[:, 1:2]
print('Print extracted column = ') # Prints "[ 2  6 10]"
print(col_r1)
print('Print shape and dims of extracted column =', col_r1.shape,col_r1.ndim)  # Prints "(3,) 1"
print('Print extracted column = ') # Prints "[[ 2]
                                   #          [ 6]
                                   #          [10]] (3, 1)"
print(col_r2)
print('Print shape and dims of extracted column = ', col_r2.shape,col_r1.ndim)  # Print "(3,1) 2"

wait = input("PRESS ENTER TO CONTINUE.")

#Array indexing:

print('Create an 4x3 integer array')
a = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])
print('Shape of the array is =', a.shape)
print()
# Create an array of indices
print('Create 1D index array')
b = np.array([0, 2, 0, 1])
print(b)
print()

# Select one element from each row of a using the indices in b
print('Create a range of indices from 0-3 using arange = ', np.arange(4))
print('Use this range to reference indices of the a array')
print(a[np.arange(4), b])  # Prints "[ 1  6  7 11]"

# Mutate one element from each row of a using the indices in b
print('Modify the indexed elements by adding 10')
a[np.arange(4), b] += 10

print('Modified array then becomes = ',a)  # prints "array([[11,  2,  3],
         #                [ 4,  5, 16],
         #                [17,  8,  9],
         #                [10, 21, 12]])

wait = input("PRESS ENTER TO CONTINUE.")

#Reference elements by boolean masks
print('Create an 3x2 numpy array')
a = np.array([[1,2], [3, 4], [5, 6]])

print('Apply a logical mask for all elements that larger than 2')
bool_idx = (a > 2)  # Find the elements of a that are bigger than 2;
                    # this returns a numpy array of Booleans of the same
                    # shape as a, where each slot of bool_idx tells
                    # whether that element of a is > 2.

print(bool_idx)      # Prints "[[False False]
                    #          [ True  True]
                    #          [ True  True]]"

# We use boolean array indexing to construct a rank 1 array
# consisting of the elements of a corresponding to the True values
# of bool_idx
print('Extracted array elements where boolean condition is true = ',a[bool_idx])  # Prints "[3 4 5 6]"

# We can do all of the above in a single concise statement:
print('The boolean condition can be an input to the array')
print(a[a > 2])     # Prints "[3 4 5 6]"

wait = input("PRESS ENTER TO CONTINUE.")

#Some arithmetic
print('Create two 2x2 arrays')
x = np.array([[1,2],[3,4]], dtype=np.float64)
y = np.array([[5,6],[7,8]], dtype=np.float64)
print()
# Elementwise sum; both produce the array
# [[ 6.0  8.0]
#  [10.0 12.0]]
#print x + y
print('Add them')
print(np.add(x, y))
print()
# Elementwise difference; both produce the array
# [[-4.0 -4.0]
#  [-4.0 -4.0]]
#print x - y
print('Subtracted them')
print(np.subtract(x, y))
print()

# Elementwise product; both produce the array
# [[ 5.0 12.0]
#  [21.0 32.0]]
#print x * y
print('Multiply by elements')
print(np.multiply(x, y))
print()

# Elementwise division; both produce the array
# [[ 0.2         0.33333333]
#  [ 0.42857143  0.5       ]]
#print x / y
print('Divide by elements')
print(np.divide(x, y))

# Elementwise square root; produces the array
# [[ 1.          1.41421356]
#  [ 1.73205081  2.        ]]
print('Square root')
print(np.sqrt(x))

x = np.array([[1,2],[3,4]])
y = np.array([[5,6],[7,8]])

print()
print('Create two 1D arrays and treat them as vectors')
v = np.array([9,10])
print(v)
w = np.array([11, 12])
print(w)
print()

# Inner product of vectors; both produce 219
#print v.dot(w)
print('Inner product = ',np.dot(v, w))

# Matrix / vector product; both produce the rank 1 array [29 67]
#print x.dot(v)
print('Matrix * vector product =',np.dot(x, v))

# Matrix / matrix product; both produce the rank 2 array
# [[19 22]
#  [43 50]]
#print(x.dot(y))
print('Matrix * Matrix product')
print(np.dot(x, y))

wait = input("PRESS ENTER TO CONTINUE.")

print('Create a 2x2 array')
x = np.array([[1,2],[3,4]])
print(x)
print()
print('Sum of all elements = ',np.sum(x))  # Compute sum of all elements; prints "10"
print('Sum of all columns =',np.sum(x, axis=0))  # Compute sum of each column; prints "[4 6]"
print('Sum of all rows = ',np.sum(x, axis=1))  # Compute sum of each row; prints "[3 7]"

x = np.array([[1,2], [3,4]])
#print x    # Prints "[[1 2]
           #          [3 4]]"
print('Transpose Matrix = ',x.T)  # Prints "[[1 3]
           #          [2 4]]"
print('Transpose Matrix (alt)= ',np.transpose(x)) # transpose matrix x using transpose

wait = input("PRESS ENTER TO CONTINUE.")

# We will add the vector v to each row of the matrix x,
# storing the result in the matrix y
print('Create a 4x3 array')
x = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])
print(x)
print()
print('Create a vector with the same number of row elements')
v = np.array([1, 0, 1])
print(v)
print()
print('Create an empty matrix with the same shape as x')
y = np.empty_like(x)   # Create an empty matrix with the same shape as x
print(y)
print()

# Add the vector v to each row of the matrix x with an explicit loop
print('Add the vector to each extracted row i x[i,:]')
for i in range(4):
    y[i, :] = x[i, :] + v

# Now y is the following
# [[ 2  2  4]
#  [ 5  5  7]
#  [ 8  8 10]
#  [11 11 13]]
print('Modified array')
print(y)
print()

wait = input("PRESS ENTER TO CONTINUE.")

print('Add vector to all matrix rows using tile')
# We will add the vector v to each row of the matrix x,
# storing the result in the matrix y
x = np.array([[1,2,3], [4,5,6], [7,8,9], [10, 11, 12]])
print('1D vector - same number of elements as the row elements of the target array')
v = np.array([1, 0, 1])
print(v)
print('tile the vector - replicate the vector 4 times and stack it to form an array')
vv = np.tile(v, (4, 1))  # Stack 4 copies of v on top of each other
print(vv)                 # Prints "[[1 0 1]
                         #          [1 0 1]
                         #          [1 0 1]
                         #          [1 0 1]]"
print('tiled vector can directly added to matrix')
y = x + vv  # Add x and vv elementwise
print(y)  # Prints "[[ 2  2  4
         #          [ 5  5  7]
         #          [ 8  8 10]
         #          [11 11 13]]"

wait = input("PRESS ENTER TO CONTINUE.")

print('Compute outer product of vectors')
print('Create vector 1x3 and vector 1x2')
v = np.array([1,2,3])  # v has shape (3,)
w = np.array([4,5])    # w has shape (2,)
print(v)
print(w)
print()

# To compute an outer product, we first reshape v to be a column
# vector of shape (3, 1); we can then broadcast it against w to yield
# an output of shape (3, 2), which is the outer product of v and w:
# [[ 4  5]
#  [ 8 10]
#  [12 15]]
print('Compute outer/tensor product v^T.w')
print('reshape vector v = ')
print(np.reshape(v,(3,1)))
print('Directly multiply 3x1 to 1x2 vectors to yield 3x2 matrix')
print(np.reshape(v, (3, 1)) * w)

wait = input("PRESS ENTER TO CONTINUE.")

print('Add a vector to each column of a matrix')
print('Create a 2x3 matrix')
x = np.array([[1,2,3], [4,5,6]])
print(x)
print()
print('Create a 1x2 vector')
w = np.array([4,5])
print(w)
print()
# x has shape (2, 3) and w has shape (2,).
# If we transpose x then it has shape (3, 2) and can be broadcast
# against w to yield a result of shape (3, 2); transposing this result
# yields the final result of shape (2, 3) which is the matrix x with
# the vector w added to each column. Gives the following matrix:
# [[ 5  6  7]
#  [ 9 10 11]]
print('Transpose x')
print(x.T)
print()
print('We can add the 1x2 vector')
print(x.T+w)
print()
print('We can transpose the 3x2 matrix back to 2x3')
print((x.T + w).T)
print()


"""
Common test functions for optimizers.

Also see: https://en.wikipedia.org/wiki/Test_functions_for_optimization
"""

def rosenbrock(x, y):
    """
    Rosenbrock function. Minimum: f(1, 1) = 0.

    https://en.wikipedia.org/wiki/Rosenbrock_function
    """
    return (1 - x) ** 2 + 100 * (y - x ** 2) ** 2

rosenbrock.errordef = 1

def rosenbrock_grad(x, y):
    """Gradient of Rosenbrock function."""
    return (-400 * x * (-(x ** 2) + y) + 2 * x - 2, -200 * x ** 2 + 200 * y)

def ackley(x, y):
    """
    Ackley function. Minimum: f(0, 0) = 0.

    https://en.wikipedia.org/wiki/Ackley_function
    """
    from math import sqrt, exp, cos, pi, e

    term1 = -20 * exp(-0.2 * sqrt(0.5 * (x ** 2 + y ** 2)))
    term2 = -exp(0.5 * (cos(2 * pi * x) + cos(2 * pi * y)))
    return term1 + term2 + 20 + e

ackley.errordef = 1

def beale(x, y):
    """
    Beale function. Minimum: f(3, 0.5) = 0.

    https://en.wikipedia.org/wiki/Test_functions_for_optimization
    """
    term1 = 1.5 - x + x * y
    term2 = 2.25 - x + x * y ** 2
    term3 = 2.625 - x + x * y ** 3
    return term1 * term1 + term2 * term2 + term3 * term3

beale.errordef = 1

def matyas(x, y):
    """
    Matyas function. Minimum: f(0, 0) = 0.

    https://en.wikipedia.org/wiki/Test_functions_for_optimization
    """
    return 0.26 * (x ** 2 + y ** 2) - 0.48 * x * y

matyas.errordef = 1

def sphere_np(x):
    """
    Sphere function for variable number of arguments. Minimum: f(0, ..., 0) = 0.

    https://en.wikipedia.org/wiki/Test_functions_for_optimization
    """
    import numpy as np

    return np.sum(x ** 2)

sphere_np.errordef = 1


import numpy as np

print "Executing: 08_Standardizing_Data.py"

# 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 this country name to change what country will be printed when you
# click "Test Run". Your function will be called to determine the standardized
# score for this country for each of the given 5 Gapminder variables in 2007.
# The possible country names are available in the Downloadables section.

country_name = 'United States'

def standardize_data(values):
    '''
    Fill in this function to return a standardized version of the given values,
    which will be in a NumPy array. Each value should be translated into the
    number of standard deviations that value is away from the mean of the data.
    (A positive number indicates a value higher than the mean, and a negative
    number indicates a value lower than the mean.)
    '''
    standardized_values = (values - values.mean()) / values.std()
    return standardized_values


# Question 1: Create a 4X2 integer array and Prints its attributes
# Note: The element must be a type of unsigned int16. And print the following Attributes: –
#
# The shape of an array.
# Array dimensions.
# The Length of each element of the array in bytes.
import numpy as np

Array = np.empty([4, 2], dtype=np.uint16)
print("Array Shape is: ", Array.shape)
print("Array dimensions are ", Array.ndim)
print("Length of each element of array in bytes is ", Array.itemsize)
# Question 2: Create a 5X2 integer array from a range between 100 to 200 such that the difference between each element is 10
import numpy as  np

a = np.arange(100, 200, 10)
b = a.reshape(5, 2)
print(b)
# Question 3: Following is the provided numPy array. return array of items in the third column from all rows
import numpy as np

sampleArray = np.array([[11, 22, 33], [44, 55, 66], [77, 88, 99]])

sampleArray = numpy.array([[11, 22, 33], [44, 55, 66], [77, 88, 99]])

newArray = sampleArray[..., 1]
print(newArray)
# Question 4: Following is the given numpy array return array of odd rows and even columns
import numpy

sampleArray = numpy.array([[3, 6, 9, 12], [15, 18, 21, 24],
                           [27, 30, 33, 36], [39, 42, 45, 48], [51, 54, 57, 60]])
print("Printing Input Array")
print(sampleArray)

print("\n Printing array of odd rows and even columns")
newArray = sampleArray[::2, 1::2]
print(newArray)
# Question 5: Add the following two NumPy arrays and Modify a result array by calculating the square of each element
# import numpy
#
# arrayOne = numpy.array([[5, 6, 9], [21 ,18, 27]])
# arrayTwo = numpy.array([[15 ,33, 24], [4 ,7, 1]])
import numpy

arrayOne = numpy.array([[5, 6, 9], [21, 18, 27]])
arrayTwo = numpy.array([[15, 33, 24], [4, 7, 1]])

resultArray = arrayOne + arrayTwo
print("addition of two arrays is \n")
print(resultArray)

for num in numpy.nditer(resultArray, op_flags=['readwrite']):
    num[...] = num * num
print("\nResult array after calculating the square root of all elements\n")
print(resultArray)
# Question 6: Split the array into four equal-sized sub-arrays
import numpy

print("Creating 8X3 array using numpy.arange")
sampleArray = numpy.arange(10, 34, 1)
sampleArray = sampleArray.reshape(8, 3)
print(sampleArray)

print("\nDividing 8X3 array into 4 sub array\n")
subArrays = numpy.split(sampleArray, 4)
print(subArrays)
# Question 7; Sort following NumPy array
# 7.1- by the second row and
# 7.2-by the second column
import numpy

print("Printing Original array")
sampleArray = numpy.array([[34, 43, 73], [82, 22, 12], [53, 94, 66]])
print(sampleArray)

sortArrayByRow = sampleArray[:, sampleArray[1, :].argsort()]
print("Sorting Original array by secoond row")
print(sortArrayByRow)

print("Sorting Original array by secoond column")
sortArrayByColumn = sampleArray[sampleArray[:, 1].argsort()]
print(sortArrayByColumn)
# Question 8: Following is the 2-D array. Print max from axis 0 and min from axis 1
# import numpy
# sampleArray = numpy.array([[34,43,73],[82,22,12],[53,94,66]])
import numpy

print("Printing Original array")
sampleArray = numpy.array([[34, 43, 73], [82, 22, 12], [53, 94, 66]])
print(sampleArray)

minOfAxisOne = numpy.amin(sampleArray, 1)
print("Printing amin Of Axis 1")
print(minOfAxisOne)

maxOfAxisOne = numpy.amax(sampleArray, 0)
print("Printing amax Of Axis 0")
print(maxOfAxisOne)
# Question 9: Following is the input NumPy array delete column two and insert following new column in its place.
# import numpy
# sampleArray = numpy.array([[34,43,73],[82,22,12],[53,94,66]])
#
# newColumn = numpy.array([[10,10,10]])
import numpy

print("Printing Original array")
sampleArray = numpy.array([[34, 43, 73], [82, 22, 12], [53, 94, 66]])
print(sampleArray)

print("Array after deleting column 2 on axis 1")
sampleArray = numpy.delete(sampleArray, 1, axis=1)
print(sampleArray)

arr = numpy.array([[10, 10, 10]])

print("Array after inserting column 2 on axis 1")
sampleArray = numpy.insert(sampleArray, 1, arr, axis=1)
print(sampleArray)
# Question 10: Create a two 2-D array and Plot it using matplotlib
import numpy

print("Printing Original array")
sampleArray = numpy.array([[34, 43, 73], [82, 22, 12], [53, 94, 66]])
print(sampleArray)

print("Array after deleting column 2 on axis 1")
sampleArray = numpy.delete(sampleArray, 1, axis=1)
print(sampleArray)

arr = numpy.array([[10, 10, 10]])

print("Array after inserting column 2 on axis 1")
sampleArray = numpy.insert(sampleArray, 1, arr, axis=1)
print(sampleArray)


import numpy as np
import torch

"""

Exercise 1.1: Diagonal Gaussian Likelihood

Write a function that takes in PyTorch Tensors for the means and
log stds of a batch of diagonal Gaussian distributions, along with a
PyTorch Tensor for (previously-generated) samples from those
distributions, and returns a Tensor containing the log
likelihoods of those samples.

"""

def gaussian_likelihood(x, mu, log_std):
    """
    Args:
        x: Tensor with shape [batch, dim]
        mu: Tensor with shape [batch, dim]
        log_std: Tensor with shape [batch, dim] or [dim]

    Returns:
        Tensor with shape [batch]
    """
    m = torch.distributions.normal.Normal(mu, torch.exp(log_std))
    return m.log_prob(x).sum(axis=-1)

if __name__ == "__main__":
    """
    Run this file to verify your solution.
    """
    from spinup.exercises.common import print_result
    from spinup.exercises.pytorch.problem_set_1_solutions import (
        exercise1_1_soln,
    )

    batch_size = 32
    dim = 10

    x = torch.rand(batch_size, dim)
    mu = torch.rand(batch_size, dim)
    log_std = torch.rand(dim)

    your_gaussian_likelihood = gaussian_likelihood(x, mu, log_std)
    true_gaussian_likelihood = exercise1_1_soln.gaussian_likelihood(
        x, mu, log_std
    )

    your_result = your_gaussian_likelihood.detach().numpy()
    true_result = true_gaussian_likelihood.detach().numpy()

    correct = np.allclose(your_result, true_result)
    print_result(correct)


import numpy as np
from os.path import exists
from matplotlib import pyplot as plt
from sklearn.manifold import TSNE

def t_sne(n_components=2):
    img = np.load(r'../data/sampled_image.npy')
    img = img.reshape((-1, img.shape[1]*img.shape[2]))
    x = TSNE(n_components=n_components).fit_transform(img)
    np.save('tsne.npy', x)

def kde(x, y, X, Y, h1, h2, kernel1, kernel2):
    kx = kernel1((x-X)/h1)
    ky = kernel2((y-Y)/h2)
    p = 1/(len(X)*h1*h2)*np.sum(kx*ky)
    return p

def gaussian(x):
    return 1/(2*np.pi)**0.5*np.exp(-x*x/2)

def epanechnikov(x):
    x_ = 3/4*(1-x*x)
    x_[(x > 1) | (x < -1)] = 0
    return x_

def densitymap(data, h1, h2, kernel1, kernel2, n=1000):
    x = np.linspace(min(data[:, 0]), max(data[:, 0]), n)
    y = np.linspace(min(data[:, 1]), max(data[:, 1]), n)
    contour = np.zeros((n, n))
    if kernel1 == 'gaussian':
        func1 = gaussian
    elif kernel1 == 'epanechnikov':
        func1 = epanechnikov
    if kernel2 == 'gaussian':
        func2 = gaussian
    elif kernel2 == 'epanechnikov':
        func2 = epanechnikov
    for i in range(n):
        for j in range(n):
            contour[i][j] = kde(x[i], y[j], data[:, 0], data[:, 1], h1, h2, func1, func2)
    X, Y = np.meshgrid(x, y)
    plt.figure(figsize=(12, 12))
    a = plt.contourf(X, Y, contour, cmap='Reds', alpha=1)
    plt.contour(X, Y, contour)
    plt.colorbar(a)
    plt.title('density map-%s-%s-%.1f-%.1f' % (kernel1, kernel2, h1, h2))
    plt.savefig('density map-%s-%s-%.1f-%.1f.png' % (kernel1, kernel2, h1, h2))
    plt.close()

if __name__ == "__main__":
    if not exists('tsne.npy'):
        t_sne()
    data = np.load('tsne.npy')
    label = np.load('../data/sampled_label.npy')
    f = plt.figure(figsize=(12, 12))
    for i in range(10):
        plt.scatter(data[label == i, 0], data[label == i, 1], label='%i' % i)
    plt.legend(loc='best')
    plt.title('T-SNE decomposition')
    plt.savefig('scatter.png')
    plt.close()
    densitymap(data, 3, 3, 'epanechnikov', 'epanechnikov')
    densitymap(data, 2, 3, 'epanechnikov', 'epanechnikov')
    densitymap(data, 2, 2, 'epanechnikov', 'epanechnikov')
    densitymap(data, 2, 2, 'gaussian', 'gaussian')
    densitymap(data, 1.5, 1.5, 'gaussian', 'gaussian')
    densitymap(data, 5, 5, 'gaussian', 'gaussian')
    densitymap(data, 3, 5, 'gaussian', 'epanechnikov')
    densitymap(data, 1.5, 3, 'gaussian', 'epanechnikov')


import numpy as np

def bias(obs, model) -> float:
    "Bias (model - obs)"
    return np.mean(model - obs)

def mean_absolute_error(
    obs: np.ndarray, model: np.ndarray, weights: np.ndarray = None
) -> float:
    """Mean Absolute Error (MAE)"""

    error = np.average(np.abs(model - obs), weights=weights)
    return error

def rmse(
    obs: np.ndarray,
    model: np.ndarray,
    weights: np.ndarray = None,
    unbiased: bool = False,
) -> float:
    return root_mean_squared_error(obs, model, weights, unbiased)

def root_mean_squared_error(
    obs: np.ndarray,
    model: np.ndarray,
    weights: np.ndarray = None,
    unbiased: bool = False,
) -> float:
    """Root Mean Squared Error (RMSE)"""
    residual = obs - model
    if unbiased:
        residual = residual - residual.mean()
    error = np.sqrt(np.average(residual ** 2, weights=weights))

    return error

def nash_sutcliffe_efficiency(obs, model) -> float:
    """Nash-Sutcliffe Efficiency (NSE)"""
    error = 1 - (np.sum((obs - model) ** 2) / np.sum((model - np.mean(model)) ** 2))

    return error

def corr_coef(obs, model) -> float:

    return np.corrcoef(obs, model)[0, 1]

def scatter_index(obs, model) -> float:

    return np.sqrt(
        np.sum(((model - model.mean()) - (obs - obs.mean())) ** 2) / np.sum(obs ** 2)
    )

def r2(obs, model) -> float:
    """Coefficient of determination"""

    residual = model - obs

    SSt = np.sum(obs ** 2)
    SSr = np.sum(residual ** 2)

    return 1 - SSr / SSt


import matplotlib.pyplot as plt
import numpy as np

from pydmd import DMD

# We create the input data by summing two different functions
# $f_1(x,t) = \text{sech}(x+3)\exp(i2.3t)$
# $f_2(x,t) = 2\text{sech}(x)\tanh(x)\exp(i2.8t)$.

def f1(x,t):
    return 1./np.cosh(x+3)*np.exp(2.3j*t)

def f2(x,t):
    return 2./np.cosh(x)*np.tanh(x)*np.exp(2.8j*t)

x = np.linspace(-5, 5, 65)
t = np.linspace(0, 4*np.pi, 129)

xgrid, tgrid = np.meshgrid(x, t)

X1 = f1(xgrid, tgrid)
X2 = f2(xgrid, tgrid)
X = X1 + X2

# The plots below represent these functions and the dataset.

titles = ['$f_1(x,t)$', '$f_2(x,t)$', '$f$']
data = [X1, X2, X]

fig = plt.figure(figsize=(17, 6))
for n, title, d in zip(range(131, 134), titles, data):
    plt.subplot(n)
    plt.pcolor(xgrid, tgrid, d.real)
    plt.title(title)
plt.colorbar()
plt.show()

# Now we have the temporal snapshots in the input matrix rows: we can easily create a new DMD instance and exploit it in order to compute the decomposition on the data. Since the snapshots must be arranged by columns, in this case we need to transpose the matrix.

dmd = DMD(svd_rank=2)
dmd.fit(X.T)

# The `dmd` object contains the principal information about the decomposition:
# - the attribute `modes` is a 2D numpy array where the columns are the low-rank structures individuated;
# - the attribute `dynamics` is a 2D numpy array where the rows refer to the time evolution of each mode;
# - the attribute `eigs` refers to the eigenvalues of the low dimensional operator;
# - the attribute `reconstructed_data` refers to the approximated system evolution.
#
# Moreover, some helpful methods for the graphical representation are provided.

# Thanks to the eigenvalues, we can check if the modes are stable or not: if an eigenvalue is on the unit circle, the corresponding mode will be stable; while if an eigenvalue is inside or outside the unit circle, the mode will converge or diverge, respectively. From the following plot, we can note that the two modes are stable.

for eig in dmd.eigs:
    print('Eigenvalue {}: distance from unit circle {}'.format(eig, np.abs(np.sqrt(eig.imag**2+eig.real**2) - 1)))

dmd.plot_eigs(show_axes=True, show_unit_circle=True)

# We can plot the modes and the dynamics:

for mode in dmd.modes.T:
    plt.plot(x, mode.real)
    plt.title('Modes')
plt.show()

for dynamic in dmd.dynamics:
    plt.plot(t, dynamic.real)
    plt.title('Dynamics')
plt.show()

# Finally, we can reconstruct the original dataset as the product of modes and dynamics. We plot the evolution of each mode to emphasize their similarity with the input functions and we plot the reconstructed data.

fig = plt.figure(figsize=(17,6))

for n, mode, dynamic in zip(range(131, 133), dmd.modes.T, dmd.dynamics):
    plt.subplot(n)
    plt.pcolor(xgrid, tgrid, (mode.reshape(-1, 1).dot(dynamic.reshape(1, -1))).real.T)

plt.subplot(133)
plt.pcolor(xgrid, tgrid, dmd.reconstructed_data.T.real)
plt.colorbar()

plt.show()

# We can also plot the absolute error between the approximated data and the original one.

plt.pcolor(xgrid, tgrid, (X-dmd.reconstructed_data.T).real)
fig = plt.colorbar()

# The reconstructed system looks almost equal to the original one: the dynamic mode decomposition made possible the identification of the meaningful structures and the complete reconstruction of the system using only the collected snapshots.


# -*- coding: utf-8 -*-
"""
Created on Fri Mar  1 17:58:33 2019

@author: Ham

HackerRanch Challenge: Min and Max

min

The tool min returns the minimum value along a given axis.

import numpy

my_array = numpy.array([[2, 5],
                        [3, 7],
                        [1, 3],
                        [4, 0]])

print numpy.min(my_array, axis = 0)         #Output : [1 0]
print numpy.min(my_array, axis = 1)         #Output : [2 3 1 0]
print numpy.min(my_array, axis = None)      #Output : 0
print numpy.min(my_array)                   #Output : 0
By default, the axis value is None.
Therefore, it finds the minimum over all the dimensions of the input array.

max

The tool max returns the maximum value along a given axis.

import numpy

my_array = numpy.array([[2, 5],
                        [3, 7],
                        [1, 3],
                        [4, 0]])

print numpy.max(my_array, axis = 0)         #Output : [4 7]
print numpy.max(my_array, axis = 1)         #Output : [5 7 3 4]
print numpy.max(my_array, axis = None)      #Output : 7
print numpy.max(my_array)                   #Output : 7
By default, the axis value is None.
Therefore, it finds the maximum over all the dimensions of the input array.

Task

You are given a 2-D array with dimensions NxM.
Your task is to perform the min function over axis 1
and then find the max of that.

Input Format

The first line of input contains the space separated values of N and M.
The next N lines contains M space separated integers.

Output Format

Compute the min along axis 1 and then print the max of that result.

Sample Input

4 2
2 5
3 7
1 3
4 0

Sample Output

3

Explanation

The min along axis 1 = [2 3 1 0]
The max of [2 3 1 0] = 3

"""

import numpy

# ignoring 2nd int of 1st line, M
a = [list(map(int, input().strip().split()))
     for _ in range(int(input().strip().split()[0]))]
print(numpy.max(numpy.min(a, axis=1)))


# -*- coding: utf-8 -*-
"""heap_sort.ipynb

Automatically generated by Colaboratory.

Original file is located at
    https://colab.research.google.com/drive/12lxwJdY5eO-QK4OOJ7WQh6mK0r87_AzB
"""

import numpy as np
import time

def max_heapify(arr, idx, n):
  while 2*idx+1 < n:
    L = 2*idx+1
    R = 2*idx+2

    if arr[idx] < arr[L]:
      m = L

    else:
      m = idx

    if R < n and arr[m] < arr[R]:
      m = R

    if idx != m:
      arr[idx], arr[m] = arr[m], arr[idx]
      idx = m

    else:
      break

def min_heapify(arr, idx, n):
  while 2*idx+1 < n:
    L = 2*idx+1
    R = 2*idx+2

    if arr[idx] > arr[L]:
      m = L

    else:
      m = idx

    if R < n and arr[m] > arr[R]:
      m = R

    if idx != m:
      arr[idx], arr[m] = arr[m], arr[idx]
      idx = m

    else:
      break

def make_heap(arr, isMaxHeap):
  if isMaxHeap == True:
    for i in range(len(arr)//2, -1, -1):
      max_heapify(arr, i, len(arr))

  else:
    for i in range(len(arr)//2, -1, -1):
      min_heapify(arr, i, len(arr))

def heap_sort(arr, isMaxHeap):
  make_heap(arr, isMaxHeap)
  n = len(arr)

  if isMaxHeap == True:
    for i in range(len(arr)-1):
      arr[0], arr[n-1] = arr[n-1], arr[0]
      n = n-1

      max_heapify(arr, 0, n)

  else:
    for i in range(len(arr)-1):
      arr[0], arr[n-1] = arr[n-1], arr[0]
      n = n-1

      min_heapify(arr, 0, n)

  return arr

def check_sort(arr, N, isMaxHeap):
  sorted = True

  if isMaxHeap==True:
    for i in range(N-1):
      if arr[i] > arr[i+1]:
        sorted = False
      if sorted == False:
        break;

    if sorted == True:
      print("Maxheap sorting complete!")
    else:
      print("Maxheap sorting error!!!")

  else:
    for i in range(N-1):
      if arr[i] < arr[i+1]:
        sorted = False
      if sorted == False:
        break;

    if sorted == True:
      print("Minheap sorting complete!")
    else:
      print("Minheap sorting error!!!")

print("MaxHeap 정렬 결과")
print(heap_sort([6, 2, 8, 1, 3, 9, 4, 5, 10, 7], isMaxHeap=True))
print("MinHeap 정렬 결과")
print(heap_sort([6, 2, 8, 1, 3, 9, 4, 5, 10, 7], isMaxHeap=False))

N_list = [10000, 50000, 100000, 500000, 1000000]

for N in N_list:
  arr = np.random.randint(low=0, high=N, size=N) # 길이가 N개인 임의의 리스트를 생성

  isMaxHeap=True
  start = time.time()
  sorted_arr = heap_sort(arr.copy(), isMaxHeap)
  cost = round(time.time() - start, 2)
  check_sort(sorted_arr, N, isMaxHeap)
  print(f"Maxheap sorting (N={N}) time cost : {cost}sec")

  isMaxHeap=False
  start = time.time()
  sorted_arr = heap_sort(arr.copy(), isMaxHeap)
  cost = round(time.time() - start, 2)
  check_sort(sorted_arr, N, isMaxHeap)
  print(f"Minheap sorting (N={N}) time cost : {cost}sec\n")

3. Algorithms/02. Sorting/Heap Sorting Design/heap_sort.py


import matplotlib.pyplot as plt
import matplotlib.image as mpimg
from matplotlib import colors
# from numba import jlt
import cv2
import numpy as np

MAX_ITERATIONS = 200
HEIGHT = 600
WIDTH = int(HEIGHT * 1.5)

def map(number, l_ini, r_ini, l_final, r_final):
	fraction = (number - l_ini) / (r_ini - l_ini)
	value = fraction * (r_final - l_final) + l_final
	return value

# @jlt
def plot_Mandelbrot_Set(image, min_x, max_x, min_y, max_y):
	for i in range(WIDTH):
		x = map(i, 0, WIDTH, min_x, max_x)
		for j in range(HEIGHT):
			z = 0 + 0j
			y = map(j, 0, HEIGHT, min_y, max_y)
			c = complex(x, y)
			curr_iteration = 0

			while abs(z) < 2 and curr_iteration < MAX_ITERATIONS:
				z = z*z + c
				curr_iteration += 1

			# if curr_iteration == MAX_ITERATIONS:
			# 	image[j][i] = 0
			# else:
			# 	image[j][i] = 255
			image[j][i] = curr_iteration

		if i % 100 == 0:
			print("Calculating Column {}".format(i))
	return image

def plot_set(image, cmap='jet', gamma=0.3):
	norm = colors.PowerNorm(gamma)
	plt.imshow(image, cmap=cmap, norm=norm)
	plt.show()

mandelbrotSet = [[0 for _ in range(WIDTH)] for _ in range(HEIGHT)]
mandelbrotSet = plot_Mandelbrot_Set(mandelbrotSet, -2.5, 1, -1, 1)

plot_set(mandelbrotSet,cmap='hot')

# cv2.imshow("set", np.array(mandelbrotSet)/255.0)
# plt.imshow(mandelbrotSet)
# plt.show()


from numpy import *
from matplotlib.pyplot import *

def solver(I, a, T, dt, theta):
    """Solve u'=-a*u, u(0)=I, for t in (0,T] with steps of dt."""
    dt = float(dt)            # avoid integer division
    Nt = int(round(T/dt))     # no of time intervals
    T = Nt*dt                 # adjust T to fit time step dt
    u = zeros(Nt+1)           # array of u[n] values
    t = linspace(0, T, Nt+1)  # time mesh

    if theta == 0:
        a = a*(1 - 0.5*a*dt)
    elif theta == 1:
        a = a*(1 + 0.5*a*dt)
    else:
        a = a*(1 - 1./12*a**2*dt**2)

    u[0] = I                  # assign initial condition
    for n in range(0, Nt):    # n=0,1,...,Nt-1
        u[n+1] = (1 - (1-theta)*a*dt)/(1 + theta*dt*a)*u[n]
    return u, t

def exact_solution(t, I, a):
    return I*exp(-a*t)

def explore(I, a, T, dt, theta=0.5, makeplot=True):
    """
    Run a case with the solver, compute error measure,
    and plot the numerical and exact solutions (if makeplot=True).
    """
    u, t = solver(I, a, T, dt, theta)  # Numerical solution
    u_e = exact_solution(t, I, a)
    e = u_e - u
    E = sqrt(dt*sum(e**2))
    if makeplot:
        figure()                         # create new plot
        t_e = linspace(0, T, 1001)       # very fine mesh for u_e
        u_e = exact_solution(t_e, I, a)
        plot(t,   u,   'r--o')           # red dashes w/circles
        plot(t_e, u_e, 'b-')             # blue line for u_e
        legend(['numerical', 'exact'])
        xlabel('t')
        ylabel('u')
        title('Method: theta-rule, theta=%g, dt=%g' % (theta, dt))
        theta2name = {0: 'FE', 1: 'BE', 0.5: 'CN'}
        savefig('%s_%g.png' % (theta2name[theta], dt))
        show()
    return E

def define_command_line_options():
    import argparse
    parser = argparse.ArgumentParser()
    parser.add_argument('--I', '--initial_condition', type=float,
                        default=1.0, help='initial condition, u(0)',
                        metavar='I')
    parser.add_argument('--a', type=float,
                        default=1.0, help='coefficient in ODE',
                        metavar='a')
    parser.add_argument('--T', '--stop_time', type=float,
                        default=1.0, help='end time of simulation',
                        metavar='T')
    parser.add_argument('--makeplot', action='store_true',
                        help='display plot or not')
    parser.add_argument('--dt', '--time_step_values', type=float,
                        default=[1.0], help='time step values',
                        metavar='dt', nargs='+', dest='dt_values')
    return parser

def read_command_line():
    parser = define_command_line_options()
    args = parser.parse_args()
    print 'I={}, a={}, T={}, makeplot={}, dt_values={}'.format(
        args.I, args.a, args.T, args.makeplot, args.dt_values)
    return args.I, args.a, args.T, args.makeplot, args.dt_values

from math import log

def main():
    I, a, T, makeplot, dt_values = read_command_line()
    r = {}  # estimated convergence rates
    for theta in 0, 0.5, 1:
        E_values = []
        for dt in dt_values:
            E = explore(I, a, T, dt, theta, makeplot=False)
            E_values.append(E)

        # Compute convergence rates
        m = len(dt_values)
        r[theta] = [log(E_values[i-1]/E_values[i])/
                    log(dt_values[i-1]/dt_values[i])
                    for i in range(1, m, 1)]

    for theta in r:
        print '\nPairwise convergence rates for theta=%g:' % theta
        print ' '.join(['%.2f' % r_ for r_ in r[theta]])
    return r

def verify_convergence_rate():
    r = main()
    tol = 0.1
    expected_rates = {0: 1, 1: 1, 0.5: 2}
    for theta in r:
        r_final = r[theta][-1]
        diff = abs(expected_rates[theta] - r_final)
        if diff > tol:
            return False
    return True  # all tests passed

# main program
main()


# coding: utf-8

# # Function hadamardmatrix

# ## Synopse
# Kernel matrix for the Hadamard Transform.
#
#    - **A = hadamardmatrix(N)**
#        - Output:
#            - **A**: Image.
#        - Input:
#            - **N**: Double.

# ## Function code

# In[5]:

import numpy as np

def hadamardmatrix(N):

    def bitsum(x):
        s = 0 * x
        while x.any():
            s += x & 1
            x >>= 1
        return s

    n = np.floor(np.log(N)/np.log(2))

    if 2**n != N:
        raise Exception('error: size {0} is not multiple of power of 2'.format(N))

    u, x = np.meshgrid(range(N), range(N))

    A = ((-1)**(bitsum(x & u)))/np.sqrt(N)
    return A

# In[1]:

testing = (__name__ == "__main__")

if testing:
    get_ipython().system(' jupyter nbconvert --to python hadamardmatrix.ipynb')
    import numpy as np
    import sys,os
    import matplotlib.image as mpimg
    ea979path = os.path.abspath('../../')
    if ea979path not in sys.path:
        sys.path.append(ea979path)
    import ea979.src as ia

# ## Examples
#
# ### Example 1

# In[2]:

if testing:
    A = ia.hadamardmatrix(128)
    ia.adshow(ia.normalize(A, [0, 255]))

# ### Example 2

# In[4]:

if testing:
    A = ia.hadamardmatrix(4)
    print(A)
    print(np.dot(A, np.transpose(A)))

# ## Measuring time:

# In[5]:

if testing:
    print('Computational time is:')
    get_ipython().magic('timeit ia.hadamardmatrix(128)')

# In[ ]:


'''
In this assignment you will implement one or more algorithms for the traveling salesman problem, such as the dynamic programming
algorithm covered in the video lectures. Here is a data file describing a TSP instance.

tsp.txt
The first line indicates the number of cities. Each city is a point in the plane, and each subsequent line indicates the x- and y-coordinates of a single city.

The distance between two cities is defined as the Euclidean distance --- that is, two cities at locations
(x, y)(x, y) and (z, w)(z, w) have distance \sqrt{(x-z)^2 + (y-w)^2}(x−z)^2+(y−w) 2 between them.

In the box below, type in the minimum cost of a traveling salesman tour for this instance, rounded down to the nearest integer.

OPTIONAL: If you want bigger data sets to play with, check out the TSP instances from around the world here. The smallest data set (Western Sahara) has 29 cities, and most of the data sets are much bigger than that. What's the largest of these data sets that you're able to solve --- using dynamic programming or, if you like, a completely different method?

HINT: You might experiment with ways to reduce the data set size. For example, trying plotting the points. Can you infer any structure of the optimal solution? Can you use that structure to speed up your algorithm?

'''

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

from collections import defaultdict, namedtuple
from tqdm import tqdm
from itertools import permutations

City = namedtuple('City', 'x y id')

data_dir = os.getcwd() + '\\data\\illuminated\\tsp\\'

submission_file_paths = data_dir + 'tsp.txt'
test_file_path = data_dir + 'tsptest3.txt'

def read_cities(file_path):

    print(f'processing {file_path}')

    with open(file_path) as f:
        lines = f.readlines()

    n_cities = int(lines[0])

    print(f'number of cities: {n_cities}')

    cities = list()
    index = 0
    for line in lines[1:]:
        x, y = map(float, line.split())
        cities += [City(x=x, y=y, id=index)]
        index += 1

    assert len(cities) == n_cities, 'length of cities does not match'
    return cities

def calculate_distance_matrix(cities):

    n = len(cities)
    distances = [[None for _ in range(n)] for _ in range(n)]

    for i in range(n):
        outer = cities[i]
        for j in range(n):
            inner = cities[j]

            distances[i][j] = math.sqrt(pow(outer.x - inner.x, 2) + pow(outer.y - inner.y, 2))

    return distances

def lexicographical_permutation(input):
    results = set()
    for perm in [''.join(chars) for chars in permutations(input)]:
        results.add(perm)
    return results

test ='00000011'
perms = lexicographical_permutation(test)
print(perms)

def find_minimum_cost_tour(cities, distances):

    num_points = len(cities)
    num_subsets = 1 << num_points

    # build lookup table for all cities
    lookup_table = [[float('inf') for _ in range(num_points)] for _ in range(num_subsets)]
    # base case
    lookup_table[1][0] = 0

    for size in range(2, num_points):

        mask_str = str('1' * size) + str('0' * (num_points - size))

        mask_permutations = lexicographical_permutation(mask_str)

        for perm in mask_permutations:

            if perm[0] == '0':
                continue

            bitmask = 1

            for index in range(num_points):
                if mask_str[index] == '1':
                    bitmask = bitmask | 1 << index

            for index in range(1, num_points):

                if (((bitmask >> index) & 1) == 1):

                    rev_bitmask = bitmask ^ (2 << index)

                    min_cost = float('inf')

                    for k in range(num_points):

                        if (((rev_bitmask >> k) & 1) == 1):
                            a, b = lookup_table[rev_bitmask][k], distances[k][index]

                            min_cost = min(a + b, min_cost)

                lookup_table[bitmask][index] = min_cost

    min_cost = float('inf')
    complete_set = num_subsets - 1

    for index in range(2, num_points):
        min_cost = min(lookup_table[complete_set][index] + distances[index][0], min_cost)

    return min_cost

def plot_cities(cities):

    data = np.array([[c.x, c.y, c.id] for c in cities])

    fig, ax = plt.subplots()

    scatter = ax.scatter(data[:, 0], data[:, 1], label=data[:, 2])

    ax.grid()
    plt.show()

cities = read_cities(test_file_path)

# plot_cities(cities)

distances = calculate_distance_matrix(cities)

min_cost_tour = find_minimum_cost_tour(cities, distances)
print(min_cost_tour)


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

# When data is non linear we use Polynomial Regression

df = pd.read_csv("FuelConsumption.csv", sep=",")
print(df.shape) #(row, columns)

"""split data in test and train"""
mask = np.random.rand(len(df)) <0.8
train = df[mask]
test = df[~mask]

"""Plot Enginesize(X) vs co2Emission(Y)"""
plt.scatter(train.ENGINESIZE, train.CO2EMISSIONS, color='blue')
plt.xlabel("Engine Size")
plt.ylabel("CO2Emission")
plt.show() # make sure tkinter or pyQt is installed if you not on notebook.

train_x = np.asanyarray(df[['ENGINESIZE']])
train_y = np.asanyarray(df[['CO2EMISSIONS']])

"""Polynomial Feature (preprocessing)"""
from sklearn.preprocessing import PolynomialFeatures
# if we select the degree of the polynomial to be 2, then it generates 3 features, degree=0, degree=1 and degree=2
#poly = PolynomialFeatures(degree=2) #In short we are using multi regression, one features is used, but with 3 thetas means we created additional features.
poly = PolynomialFeatures(degree=3)
train_x_transformed = poly.fit_transform(train_x)

"""Model Data and Fit line"""
from sklearn import linear_model
poly_non = linear_model.LinearRegression()
poly_non.fit(train_x_transformed, train_y)
print(f'Intercept : {poly_non.intercept_}')
print(f'Coefficients : {poly_non.coef_}')

"""Plot fit line"""
plt.scatter(train.ENGINESIZE, train.CO2EMISSIONS, color='blue')
XX = np.arange(0.0, 10.0, 0.1)#(start,stop,step)
#yy = poly_non.intercept_[0]+ poly_non.coef_[0][1]*XX+ poly_non.coef_[0][2]*np.power(XX, 2)
yy = poly_non.intercept_[0]+ poly_non.coef_[0][1]*XX + poly_non.coef_[0][2]*np.power(XX, 2) + poly_non.coef_[0][3]*np.power(XX, 3)
#print(len(yy),len(XX))
plt.plot(XX, yy, '-r' ) #plot fit line graph
plt.xlabel("Engine Size")
plt.ylabel("CO2Emission")
plt.show()

"""Evaluation"""
test_x = np.asanyarray(test[['ENGINESIZE']]) #2D array [[]]
test_y = np.asanyarray(test[['CO2EMISSIONS']])

test_x_poly = poly.transform(test_x) #poly transform degree 2, use simple tranform not for fit
test_pred_y = poly_non.predict(test_x_poly)

from sklearn.metrics import r2_score
print("Mean absolute error: %.2f" % np.mean(np.absolute(test_pred_y - test_y)))
print("Residual sum of squares (MSE): %.2f" % np.mean((test_pred_y - test_y) ** 2))
print("R2-score: %.2f" % r2_score(test_y , test_pred_y) )
#change value of degree to see its effect on results


# util.py

from math import floor, log, sqrt
import numpy
from numpy import dot, eye

EPS = 1.e-4 # tolerance for floating-point comparison

def is_unitary(A):
    """Indicates whether or not the matrix A is unitary."""
    return numpy.max(abs(dot(A, A.conj().T) - eye(A.shape[0]))) < EPS

def gcd(a, b):
    """Returns the greatest common divisor of a and b, using the Euclidean
    algorithm."""
    if a <= 0 or b <= 0:
        raise ValueError('Arguments must be positive integers')

    while b != 0:
        tmp = b
        b = a % b
        a = tmp
    return a

def is_prime(n):
    """Tests whether n is prime.

    This uses a naive algorithm that would be useless for numbers of substantial
    size, but is fine for the purposes of QAS, which are understanding and
    simulating the use of quantum computing rather than actually solving
    difficult problem instances.
    """
    if  n <= 1:
        raise ValueError('n must be greater than 1')

    # trial  division
    for k in range(2, int(floor(sqrt(n))) + 1):
        if n % k == 0:
            return False
    return True

def int_root(n):
    """Checks whether n is the k-th power of an integer for some k > 1. If so,
    it returns the root r such that r^k = n. Otherwise, returns -1."""
    if n <= 0:
        raise ValueError('n must be positive')
    k = 2
    while k <= log(n, 2):
        root = n**(1. / k)
        iroot = round(root)
        if iroot**k == n:
            return iroot
        k += 1
    return -1


import numpy as np

def cartesian_to_celestial(vector):
    """
    Convert the Cartesian vector [x, y, z] to spherical coordinates [r, theta, phi].
    The parameter r is the radial distance, theta is the polar angle, and phi is the azimuth.

    Arguments:
        :np.ndarray: cartesian vector [x, y, z]

    Returns:
        :np.ndarray: spherical coordinate vector [phi, theta, r]
    """
    vector = np.atleast_2d(vector)
    D = np.linalg.norm(vector, axis = -1)
    unit = np.array([v/np.linalg.norm(v) for v in vector])
    dec = np.arcsin(unit[:,2])
    ra = np.arctan2(unit[:,0], unit[:,1])
    ra[ra<0] += 2*np.pi
    return np.array([ra,dec,D]).T

def celestial_to_cartesian(vector):
    """
    Convert the celestial coordinate vector [phi, theta, r] to the Cartesian vector [x, y, z].
    The parameter r is the radial distance, theta is the polar angle, and phi is the azimuth

    Arguments:
        :np.ndarray vector: celestial coordinate vector [ra, dec, dist]

    Returns:
        :np.ndarray: cartesian vector [x, y, z]
    """
    vector = np.atleast_2d(vector)
    # Trig alias.
    cos_theta = np.cos(vector[:,1])
    # The vector.
    x = vector[:,2] * np.sin(vector[:,0]) * cos_theta
    y = vector[:,2] * np.cos(vector[:,0]) * cos_theta
    z = vector[:,2] * np.sin(vector[:,1])
    return np.array([x,y,z]).T

def Jacobian(cartesian_vect):
    """
    Computes the jacobian of celestial transformation for a cartesian vector

    Arguments:
        :np.ndarray cartesian_vect: cartesian vector [x, y, z]

    Returns:
        :np.ndarray: Jacobian of the transformation
    """
    return Jacobian_in_celestial(cartesian_to_celestial(np.atleast_2d(cartesian_vect)))

def inv_Jacobian(celestial_vect):
    """
    Computes the inverse jacobian of celestial transformation for a celestial vector

    Arguments:
        :np.ndarray cartesian_vect: cartesian vector [ra, dec, D]

    Returns:
        :np.ndarray: inverse Jacobian of the transformation
    """
    detJ = Jacobian_in_celestial(np.atleast_2d(celestial_vect))
    return 1/detJ

def Jacobian_in_celestial(celestial_vect):
    """
    Computes the jacobian of celestial transformation

    Arguments:
        :np.ndarray cartesian_vect: cartesian vector [ra, dec, D]

    Returns:
        :np.ndarray: Jacobian of the transformation
    """
    d = celestial_vect[:,2]
    theta = celestial_vect[:,1]
    return d*d*np.cos(theta)


"""
Exercise 6.1.9: Dipole fixed point
"""
import argparse
import matplotlib.pyplot as plt
import numpy as np
import sys

from phase_plane.runge_kutta import runge_kutta

def f(v):
    """
    The right-hand side of the system of differential equations.

    ..math:: \dot{x} = 2xy, \dot{y} = y^2-x^2
    """
    x = v[0]
    y = v[1]
    return np.array([2 * x * y, y**2 - x**2])

def setup_cli(args):
    """
    Setup up command-line parser.
    """
    parser = argparse.ArgumentParser(description='Exercise 6.1.8: Van der Pol oscillator.')
    parser.add_argument('-p', type=int, default=15, help='The number of points to use in the x and y direction.')
    parser.add_argument('--x_min', type=float, default=-3.5, help='Minimal value of x to be plotted.')
    parser.add_argument('--x_max', type=float, default=+3.5, help='Minimal value of x to be plotted.')
    parser.add_argument('--y_min', type=float, default=-3.5, help='Minimal value of y to be plotted.')
    parser.add_argument('--y_max', type=float, default=+3.5, help='Minimal value of y to be plotted.')
    parser.add_argument('--delta_t', type=float, default=0.01, help='Time step used in the numerical solution of the DE.')
    parser.add_argument('--end_t', type=float, default=1.0, help='Final time in the solution of the DE (Starting from t=0).')
    return parser.parse_args(args)

if __name__ == "__main__":
    # Parse command-line arguments
    args = setup_cli(sys.argv[1:])

    # Draw vector field
    x, y = np.meshgrid(np.linspace(args.x_min, args.x_max, args.p), np.linspace(args.y_min, args.y_max, args.p))
    u = 2*x*y
    v = y**2 - x**2

    plt.title('Dipole Fixed Point')
    plt.xlabel('x')
    plt.ylabel('y')
    plt.xlim(args.x_min, args.x_max)
    plt.ylim(args.y_min, args.y_max)
    plt.quiver(x, y, u, v)

    # Draw phase portraits
    x0 = [0.5, 0.5]
    t, xy = runge_kutta(f, x0, 0, 100, 0.01)
    x, y = xy.T[0], xy.T[1]
    plt.plot(x, y, c=f"C1", label=f'x0={x0}')

    x0 = [-3., -3.0]
    t, xy = runge_kutta(f, x0, 0, 100, 0.01)
    x, y = xy.T[0], xy.T[1]
    plt.plot(x, y, c=f"C2", label=f'x0={x0}')

    x0 = [-2.5, -1.5]
    t, xy = runge_kutta(f, x0, 0, 100, 0.01)
    x, y = xy.T[0], xy.T[1]
    plt.plot(x, y, c=f"C3", label=f'x0={x0}')

    x0 = [-2.5, -1.]
    t, xy = runge_kutta(f, x0, 0, 100, 0.01)
    x, y = xy.T[0], xy.T[1]
    plt.plot(x, y, c=f"C4", label=f'x0={x0}')

    x0 = [-2.5, 1.]
    t, xy = runge_kutta(f, x0, 0, 100, 0.01)
    x, y = xy.T[0], xy.T[1]
    plt.plot(x, y, c=f"C5", label=f'x0={x0}')

    x0 = [0.5, 0.5]
    t, xy = runge_kutta(f, x0, 0, 100, 0.01)
    x, y = xy.T[0], xy.T[1]
    plt.plot(x, y, c=f"C6", label=f'x0={x0}')

    # Plot everything
    plt.legend()
    plt.show()


"""
stats functions for mean, median, mode,
variance, standard deviation, and coefficient of variation
"""

import numpy as np

class Stats:

    def __init__(self, data):
        self.data = list(data)
        self.size = len(data)

    def mean(self):
        """
        function to calculate mean of data
        """
        mean = sum(self.data)/self.size
        return mean

    def median(self):
        """
        function to calculate median of data
        """
        self.data.sort()

        if len(self.data) % 2 == 1:
            median = self.data[int(self.size/2)]
        else:
            median = (self.data[int(self.size/2 - 1)] +
                    self.data[int(self.size/2)]) / 2
        return median

    def mode(self):
        """
        function to get mode of data, only returns the first it encounters if
        there are more than 1 mode
        """
        mode = max(self.data, key=self.data.count)
        return mode

    def variance(self, sample=True):
        """
        function to calculate variance of data

        by default, it calculates sample variance, change sample=False if you
        want to calculate population.
        """
        distance_squared = list(map(lambda x: (x - sum(self.data)/self.size)**2, self.data))

        if sample == True:
            variance = sum(distance_squared)/(self.size - 1)
        if sample == False:
            variance = sum(distance_squared)/(self.size)
        return variance

    def stddev(self, sample=True):
        """
        function to calculate standard deviation of data

        by default, it calculates sample standard deviation, change
        sample=False if you want to calculate population.
        """
        distance_squared = list(map(lambda x: (x - sum(self.data)/self.size)**2, self.data))

        if sample == True:
            variance = sum(distance_squared)/(self.size - 1)
            stddev = variance**(1/2)
        if sample == False:
            variance = sum(distance_squared)/(self.size)
            stddev = variance**(1/2)
        return stddev

    def coeffvar(self, sample=True):
        """
        function to calculate the coefficient of variance of data

        by default, it calculates sample coefficient of variance, change
        sample=False if you want to calculate population.
        """
        mean = sum(self.data)/self.size
        distance_squared = list(map(lambda x: (x - sum(self.data)/self.size)**2, self.data))

        if sample == True:
            variance = sum(distance_squared)/(self.size - 1)
            stddev = variance**(1/2)
            coeffvar = stddev/mean
        if sample == False:
            variance = sum(distance_squared)/(self.size)
            stddev = variance**(1/2)
            coeffvar = stddev/mean
        return coeffvar


import numpy as np
from numpy import linalg as LA

def covariance(x, y):
    x_mean = np.mean(x)
    y_mean = np.mean(y)
    x_diff = x - x_mean
    y_diff = y - y_mean
    cov_xy = np.sum(np.multiply(x_diff, y_diff))/(x.size-1)

    return cov_xy

class SingleValueDecompositon:

    def SVD(self, A):
        A = np.array(A)

        M1 = np.dot(A,A.T)

        M2 = np.dot(A.T,A)

        eig_val1, eig_vec1 = LA.eig(M1)
        sg_val = np.flip(np.sort(np.sqrt(eig_val1)))
        # U = eig_vec1[:,np.flip(np.argsort(eig_val1))]

        eig_val2, eig_vec2 = LA.eig(M2)
        # print(eig_vec2)
        V = eig_vec2[:,np.flip(np.argsort(eig_val2))]

        S = np.zeros(A.shape)
        for i in range(len(sg_val)):
            S[i][i] = sg_val[i]
        U=[]
        # print(np.dot(A,V[:,0].T))
        for idx, i in enumerate(sg_val):
            U.append(np.dot(A,V[:,idx].T)/i)
        U=np.array(U).T
        # print("U: ",U)
        # print("S: ",S)
        # print("V: ",V)
        # print("A:")
        A_r = np.dot(np.dot(U, S),V.T)

        # print(np.allclose(A,A_r))
        if np.allclose(A, A_r):
            return U, S, V

class TotalLeastSquare:
    def fit_line(self, x, y):
        x = np.array(x)
        y = np.array(y)

        x_mean = np.mean(x)
        y_mean = np.mean(y)
        U = np.vstack([x-x_mean, y-y_mean]).T
        A = np.dot(U.T, U)
        svd = SingleValueDecompositon()
        U, S, V = svd.SVD(A)
        a, b = V[:, V.shape[1]-1]
        d = a*x_mean + b*y_mean
        m = -a/b
        c = d/b

        return m, c

class LinearLeastSquare:

    def fit_line(self, x, y):
        x = np.array(x)
        y = np.array(y)
        x_square_sum = np.sum(np.square(x))

        x_mean = np.mean(x)
        y_mean = np.mean(y)
        x_sum = np.sum(x)
        y_sum = np.sum(y)
        xy_sum = np.sum(np.multiply(x,y))
        n = x.size
        ss_xx = x_square_sum - x_sum**2/n
        ss_xy = xy_sum - x_sum*y_sum/n

        m = ss_xy/ss_xx
        c = y_mean - m*x_mean

        return m,c
    def fit_parabola(self, x, y):
        x = np.array(x)
        y = np.array(y)
        x_square = np.square(x)
        A = np.vstack([x_square,x,np.ones(x.size)]).T
        Y = y.reshape(-1,1)
        beta = np.dot((np.dot(np.linalg.inv(np.dot(A.T,A)),A.T)),Y)
        return beta

class RANSAC():

    def computerError(self, x, y, m, c):
        error = y - m*x - c
        return error**2
    def fit_line(self, x, y, threshold, p=0.95, e=0.5, optimal_fit = False):
        N = int(np.ceil(np.log(1-p)/np.log(1 - np.power(1 - e, 2))))
        n = 2
        N = np.max([N, 50])
        x = np.array(x)

        y = np.array(y)
        m_best = 0
        c_best = 0
        n_inliers_max=0
        inlier_mask_best = np.zeros(x.size)
        for i in range(N):

            idxs_r = np.random.choice(x.size, size = n)

            x_r = x[idxs_r]
            y_r = y[idxs_r]

            ls = LinearLeastSquare()
            m, c = ls.fit_line(x_r, y_r)

            error_list = self.computerError(x, y, m, c)
            inlier_mask = error_list<threshold
            # print(error_list, inlier_mask)
            n_inliers = np.count_nonzero(error_list<threshold)
            # print("n_in", n_inliers)
            # print("n_max", n_inliers_max)
            if n_inliers > n_inliers_max:
                n_inliers_max = n_inliers
                m_best = m
                c_best = c
                inlier_mask_best = inlier_mask

            if n_inliers_max/x.size >= p:
                print("HERE")
                break
        # plt.scatter(x[np.invert(inlier_mask_best)], y[np.invert(inlier_mask_best)], color = 'tab:orange')
        # plt.scatter(x[inlier_mask_best], y[inlier_mask_best], color='b')
        # print(np.invert(inlier_mask_best))
        # print(m_best, c_best)
        # y1 = m_best*x + c_best
        # plt.plot(x, y1, color='r')
        # plt.show()
        if optimal_fit:
            m_best, c_best = ls.fit_line(x[inlier_mask_best], y[inlier_mask_best])
        return m_best, c_best, inlier_mask_best


from sympy import *

m1,m2,r1,r2,i1,i2,l1,l2,a1,a2,t,g = symbols('m1 m2 r1 r2 i1 i2 l1 l2 a1 a2 t g')

# positions
x1 = r1*sin(a1(t))
y1 = -r1*cos(a1(t))
x2 = l1*sin(a1(t)) + r2*sin(a1(t)+a2(t))
y2 = -l1*cos(a1(t)) - r2*cos(a1(t)+a2(t))

# velocities
x1d = diff(x1,t)
y1d = diff(y1,t)
x2d = diff(x2,t)
y2d = diff(y2,t)
a1d = diff(a1(t),t)
a2d = diff(a2(t),t)

# linear kinetic energy
Tlin1 = 0.5 * m1 * ((x1d*x1d) + (y1d*y1d))
Tlin2 = 0.5 * m2 * ((x2d*x2d) + (y2d*y2d))

# rotational kinetic energy
Trot1 = 0.5 * i1 * a1d * a1d
Trot2 = 0.5 * i2 * (a1d+a2d) * (a1d+a2d)

# total kinetic energy
T = Tlin1 + Tlin2 + Trot1 + Trot2

# potential energy
U1 = m1 * g * ( r1*(1-cos(a1(t))) )
U2 = m2 * g * ( l1*(1-cos(a1(t))) + r2*(1-cos(a1(t)-a2(t))) )
U = U1 + U2

# lagrangian L
L = T - U
L = nsimplify(L)

# compute generalized forces (toruqes) Qj
dldq1 = simplify(diff(L,a1(t)))
dldqd1 = simplify(diff(L,diff(a1(t),t)))
ddtdldqd1 = simplify(diff(dldqd1,t))
Q1 = ddtdldqd1 - dldq1

dldq2 = simplify(diff(L,a2(t)))
dldqd2 = simplify(diff(L,diff(a2(t),t)))
ddtdldqd2 = simplify(diff(dldqd2,t))
Q2 = ddtdldqd2 - dldq2

# simplify!
# converts floats that are really integers to integers, gets rid of "1.0"
Q1 = simplify(nsimplify(Q1))
Q2 = simplify(nsimplify(Q2))
# magic sauce to further simplify with some trigonometric identities
Q1 = Q1.rewrite(exp).expand().powsimp().rewrite(sin).expand()
Q2 = Q2.rewrite(exp).expand().powsimp().rewrite(sin).expand()
# collect derivative terms
Q1 = collect(Q1, Derivative(Derivative(a1(t),t),t))
Q1 = collect(Q1, Derivative(Derivative(a2(t),t),t))
Q2 = collect(Q2, Derivative(Derivative(a1(t),t),t))
Q2 = collect(Q2, Derivative(Derivative(a2(t),t),t))
# collect sin() terms
Q1 = collect(Q1, sin(a1(t)))
Q2 = collect(Q2, sin(a1(t)))

pprint(Q1)
pprint(Q2)


from math import e, pi
from typing import List

import numpy as np

def fft(p: List[complex]) -> List[complex]:
    # radix 2 Cooley-Tukey algorithm
    n = len(p)

    if not n and (not (n & (n - 1))):  # check if n is power of 2
        raise ValueError("This implementation requires arrays with length power of two")

    if n == 1:
        return p

    y_even, y_odd = fft(p[::2]), fft(p[1::2])

    omega = e ** (-2j * pi / n)  # primitive nth root of unity
    y = [0] * n
    for i in range(n // 2):
        y[i] = y_even[i] + omega ** i * y_odd[i]
        y[i + n // 2] = y_even[i] - omega ** i * y_odd[i]
    return y

def ifft(p: List[complex]) -> List[complex]:
    # Take complex conjugates
    p = [np.conj(x) for x in p]
    # Calculate normal fft
    p = fft(p)
    # Take complex conjugates again and scale by 1/n
    n = len(p)
    return [1 / n * np.conj(x) for x in p]

def test_fft_ifft():
    # Random 7th degree polynomial with coefficients from (-10, 10)
    x = np.random.rand(8) * 20 - 10

    # Verify fft gives same results as numpy's fft
    assert np.allclose(fft(x), np.fft.fft(x))
    assert np.allclose(ifft(x), np.fft.ifft(x))
    assert np.allclose(ifft(fft(x)), x)

if __name__ == "__main__":
    test_fft_ifft()


import numpy as np
import matplotlib.pyplot as plt

def map_lin_to_log(val, base):
    # it has to be defined with a min=0.0 and max=1.0
    return base**(1.0 - val)

def shift_normalize(val, base):
    # it has to be defined with min=0.0
    shift_val = map_lin_to_log(0.0, base)
    val -= shift_val
    # it has to be defined with max=1.0
    norm_val = map_lin_to_log(1.0, base) - shift_val
    val /= norm_val
    return val

def shape_function_lin(val): return 1-val

def shape_function_exp(val, exp): return (1-val)**exp

# TODO: implement checks for min=0.0 and max=1.0
# 0.0 pure shear -> less values
# 1.0 pure bending -> more values
my_exp = 3
my_power = 2
my_base = 10**my_power

alpha = np.linspace(0.0, 1.0, 25)

my_mapped_val = [shift_normalize(
    map_lin_to_log(val, my_base), my_base) for val in alpha]

# linear shape functions for linearly spaced values
n1_s = [shape_function_lin(val) for val in alpha]
n1_b = [1-val for val in n1_s]

# exponential shape functions for log spaced values
n2_s = [shape_function_exp(val, my_exp) for val in my_mapped_val]
n2_b = [1-val for val in n2_s]

#
for my_val in np.linspace(0.0, 1.0, 10):
    print('my_val: ', my_val)
    print('n2_s: ', shape_function_exp(shift_normalize(
        map_lin_to_log(my_val, my_base), my_base), my_exp))
    print('n2_b: ', 1-shape_function_exp(shift_normalize(
        map_lin_to_log(my_val, my_base), my_base), my_exp))
    print('\n')
#

plt.figure(1)
plt.title('Linear spacing mapped to log')
plt.plot(alpha, alpha, marker='o', label='original')
plt.plot(alpha, my_mapped_val, marker='<', label='mapped')
plt.legend()

plt.figure(2)
plt.title('Linear spacing and linear shape functions')
plt.plot(alpha, n1_b, marker='o', label='n1_b')
plt.plot(alpha, n1_s, marker='<', label='n1_s')
plt.legend()

plt.figure(3)
plt.title('Lin-to-log spacing and exp shape functions')
plt.plot(my_mapped_val, n2_b, marker='o', label='n2_b')
plt.plot(my_mapped_val, n2_s, marker='<', label='n2_s')
plt.legend()

plt.figure(4)
plt.title('Lin-to-log spacing and exp shape functions')
plt.semilogy(my_mapped_val, n2_b, marker='o', label='n2_b')
plt.semilogy(my_mapped_val, n2_s, marker='<', label='n2_s')
plt.legend()

plt.show()


import numpy as np

a = np.array([0, 30, 45, 60, 90])
print('不同角度的正弦值：')
# 通过乘 pi/180 转化为弧度
print(np.sin(a * np.pi / 180))
print('\n')
print('数组中角度的余弦值：')
print(np.cos(a * np.pi / 180))
print('\n')
print('数组中角度的正切值：')
print(np.tan(a * np.pi / 180))

a = np.array([0, 30, 45, 60, 90])
print('含有正弦值的数组：')
sin = np.sin(a * np.pi / 180)
print(sin)
print('\n')
print('计算角度的反正弦，返回值以弧度为单位：')
inv = np.arcsin(sin)
print(inv)
print('\n')
print('通过转化为角度制来检查结果：')
print(np.degrees(inv))
print('\n')
print('arccos 和 arctan 函数行为类似：')
cos = np.cos(a * np.pi / 180)
print(cos)
print('\n')
print('反余弦：')
inv = np.arccos(cos)
print(inv)
print('\n')
print('角度制单位：')
print(np.degrees(inv))
print('\n')
print('tan 函数：')
tan = np.tan(a * np.pi / 180)
print(tan)
print('\n')
print('反正切：')
inv = np.arctan(tan)
print(inv)
print('\n')
print('角度制单位：')
print(np.degrees(inv))

a = np.array([1.0, 5.55, 123, 0.567, 25.532])
print('原数组：')
print(a)
print('\n')
print('舍入后：')
print(np.around(a))
print(np.around(a, decimals=1))
print(np.around(a, decimals=-1))

a = np.array([-1.7, 1.5, -0.2, 0.6, 10])
print('提供的数组：')
print(a)
print('\n')
print('取整 修改后的数组：')
print(np.floor(a))

a = np.array([-1.7, 1.5, -0.2, 0.6, 10])
print('提供的数组：')
print(a)
print('\n')
print('向上取整 修改后的数组：')
print(np.ceil(a))


import numpy as np

def sigmoid(z):
	"""
	Compute a sigmoid function
	"""
	return 1.0 / (1.0 + np.exp(-z))

def sigmoid_grad(z):
	"""
	Compute the gradient of a sigmoid function
	"""
	sig_z = sigmoid(z)
	return sig_z * (1.0 - sig_z)

def cost_function(params, input_lyr_sz, hidden_lyr_sz, n_labels, X, y, lmbda):
	"""

	"""
	Theta1 = np.reshape(params[0:hidden_lyr_sz * (input_lyr_sz, + 1)], [hidden_lyr_sz, input_lyr_sz, + 1], order='F')
	Theta2 = np.reshape(params[hidden_lyr_sz * (input_lyr_sz + 1):], [n_labels, hidden_lyr_sz + 1], order='F')
	m = np.shape(X)[0]
	a1 = np.hstack((np.ones(m, 1), X))
	z2 = np.dot(a1, Theta1.T)
	a2 = sigmoid(z2)
	a2 = np.hstack((np.ones(m, 1), a2))
	z3 = np.dot(a2, Theta2.T)
	a3 = sigmoid(z3)
	ey = np.identity(n_labels)
	y = ey[y, :]
	reg_Theta1 = Theta1[:,1:]
	reg_Theta2 = Theta2[:,1:]
	reg = (lmbda / (2.0 * m)) * np.sum(np.ravel(reg_Theta1) ** 2) + np.sum(np.ravel(reg_Theta2 ** 2))
	J = (1.0 / m) + np.sum(np.sum(np.multiply(-y, np.log(a3)) - np.multiply(1 - y, np.log(1 - a3)))) + reg
	d3 = a3 - y
	d2 = np.multiply(np.dot(d3, Theta2[:,1:]), sigmoid_grad(z2))
	Theta1_grad = (1 / m) * (np.dot(d2.T, a1) + lmbda * Theta1)
	Theta2_grad = (1 / m) * (np.dot(d3.T, a2) + lmbda * Theta2)
	reg1 = np.multiply(lmbda / m, Theta1[:,0])
	reg2 = np.multiply(lmbda / m, Theta2[:,0])
	Theta1_grad[:,0] = Theta1_grad[:,0] - reg1;
	Theta2_grad[:,0] = Theta2_grad[:,0] - reg2;
	grad = np.vstack((np.ravel(Theta1_grad), np.ravel(Theta2_grad)))
	return J, grad

def predict(Theta1, Theta2, X):
	"""

	"""
	m = np.shape(X)[0]
	h1 = sigmoid(np.dot(np.hstack((np.ones(m, 1), X)), Theta1.T))
	h2 = sigmoid(np.dot(np.hstack((np.ones(m, 1), h1)), Theta2.T))
	return np.argmax(h2, axis=1)

def rand_init_weights(L_in, L_out, epsilon):
	"""

	"""
	return np.rand(L_out, 1 + L_in) * 2 * epsilon - epsilon


import numpy as np
import pandas as pd
import sys
sys.path.append("..")
import MetaFunctions as mf

#Reading in the iris data to test the meta functions with.
#Iris was chosen as it is one the most well known datasets.
iris = pd.read_csv('../Data/iris.csv', delimiter= ',', quoting= 3)
y = np.asarray(iris.iloc[:,-1])
X = np.asarray(iris.drop(iris.columns[-1], axis=1))
#This are the already known meta values of iris that were calculated using excel
no_features = 4
no_instances = 150
class_entropy = 1.584962500721156
mean_mutual_info = 0.7399384184312428
feature_entropy = 4.483305040525429

def test_compute_n_features():
    global X
    assert  mf.compute_n_features(X) == 4

def test_compute_n_classes():
    global y
    assert mf.compute_n_classes(y) == 3

def test_compute_dimensionality():
    global y
    assert mf.compute_dimensionality(150, 4) == 37.5

#Testing the correlation between each feature and the target
#then taking the mean
def test_compute_mean_correlation():
    global iris
    assert mf.compute_mean_correlation(iris) == 1.3069313703926795

#testing the skewnesss of the data
def test_compute_mean_skewness():
    global iris
    assert mf.compute_mean_skewness(iris) == 0.05390056083822681

#testing the kurtosis of the data
def test_compute_mean_kurtosis():
    global X
    assert mf.compute_mean_kurtosis(X) == -0.7656823989531729

#testing the entropy of each feature than return the average
def test_compute_mean_feature_entropy():
    global X
    assert mf.compute_mean_feature_entropy(X) == 4.483305040525429

#testsing the entropy of the targets
def test_compute_entropy():
    global y
    assert mf.compute_entropy(y) == 1.584962500721156

#testing the mean and max mutual info
def test_compute_mutual_info():
    global X
    global y
    mi = mf.compute_mutual_info(X,y)
    assert mi[0] == 0.7399384184312428
    assert mi[1] == 1.002510220562348

#testing the equivalent number of features
def test_compute_equiv_n_features():
    global class_entropy
    global mean_mutual_info
    assert mf.compute_equiv_n_features(class_entropy,
                                       mean_mutual_info) == 2.142019472487271

#testing the noise signal ratio
def test_compute_noise_signal_ratio():
    global feature_entropy
    global mean_mutual_info
    assert mf.compute_noise_signal_ratio(feature_entropy,
                                         mean_mutual_info) == 5.059024546975905


import matplotlib.pyplot as plt
import numpy as np
from matplotlib import cm
from matplotlib.ticker import FormatStrFormatter
from matplotlib.ticker import LinearLocator

from mpl_toolkits.mplot3d.axes3d import Axes3D

def f(x0: np.ndarray, x1: np.ndarray) -> np.ndarray:
    """Rosenbrock Funktion."""
    return 100 * (x0 ** 2 - x1) ** 2 + (x0 - 1) ** 2

def f_prime_x0(x0: np.ndarray, x1: np.ndarray) -> np.ndarray:
    """Derivative of f w.r.t. x0."""
    return 2 * (200 * x0 * (x0 ** 2 - x1) + x0 - 1)

def f_prime_x1(x0: np.ndarray, x1: np.ndarray) -> np.ndarray:
    """Derivative of f w.r.t. x0."""
    return -200 * (x0 ** 2 - x1)

def plot_rosenbrock(x_start: np.ndarray, gradient_steps: list = None) -> None:
    """Plot the gradient steps."""
    fig = plt.figure(figsize=(12, 8))
    ax = Axes3D(fig)

    s = 0.3
    X = np.arange(-2, 2.0 + s, s)
    Y = np.arange(-2, 3.0 + s, s)

    # Create the mesh grid(s) for all X/Y combos.
    X, Y = np.meshgrid(X, Y)
    # Rosenbrock function w/ two parameters using numpy Arrays
    Z = f(X, Y)

    surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, linewidth=0, alpha=0.8, cmap=cm.coolwarm)
    # Global minimum
    ax.scatter(1, 1, f(1, 1), color="red", marker="*", s=200)
    # Starting point
    x0, x1 = x_start
    ax.scatter(x0, x1, f(x0, x1), color="green", marker="o", s=200)

    # Eps off set of the z axis, to plot the points above the surface for better visualization
    eps = 50
    if gradient_steps:
        for (x0, x1) in gradient_steps:
            ax.scatter(x0, x1, f(x0, x1) + eps, color="green", marker="o", s=25)

    ax.set_xlabel("x")
    ax.set_ylabel("y")
    ax.set_zlabel("z")
    ax.zaxis.set_major_locator(LinearLocator(10))
    ax.zaxis.set_major_formatter(FormatStrFormatter("%.02f"))
    fig.colorbar(surf, shrink=0.5, aspect=5)
    plt.show()


import numpy

def gauss_elimination(A, b):
    """
    Solve A x = b
    """
    n = len(b)
    aug = numpy.hstack((A, numpy.reshape(b, (n, 1))))
    # Elimination
    for col in range(n):
        for row in range(col+1,n):
            pivot = aug[row,col] / aug[col,col]
            aug[row,:] -= pivot * aug[col,:]
    # Back substitution
    x = numpy.zeros_like(b)
    for row in range(n-1,-1,-1):
        x[row] = aug[row, -1] / aug[row, row]
        for col in range(row+1,n):
            x[row] -=  aug[row, col] * x[col] / aug[row, row]
    return x

def test_diagonal():
    A = numpy.identity(2)
    b = numpy.ones((2,))
    assert(numpy.all(b == gauss_elimination(A, b)))

def test_full():
    A = numpy.array([[1.0, 2.0], [3.0, 4.0]])
    b = numpy.array([5.0, 6.0])
    x_exact = [-4.0, 4.5]
    assert(numpy.all(x_exact == gauss_elimination(A, b)))

def test_pivoting():
    A = numpy.array([[1.0e-20, 1.0], [1.0, 1.0]])
    b = numpy.array([1.0, 2.0])
    x_exact = [1.0, 1.0]
    assert(numpy.all(x_exact == gauss_elimination(A, b)))


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

def dist(a, b):
  return (a - b) ** 2

def dtw(a, b):
  m = len(a)
  n = len(b)
  f = [[0] * n for i in range(m)]
  trace = [[0] * n for i in range(m)]

  f[0][0] = dist(a[0], b[0])
  trace[0][0] = (-1, -1)

  for i in range(1, m):
    f[i][0] = f[i - 1][0] + dist(a[i], b[0])
    trace[i][0] = (i - 1, 0)

  for i in range(1, n):
    f[0][i] = f[0][i - 1] + dist(a[0], b[i])
    trace[0][i] = (0, i - 1)

  for i in range(1, m):
    for j in range(1, n):
      if f[i - 1][j] < f[i][j - 1] and f[i - 1][j] < f[i - 1][j - 1]:
        f[i][j] = f[i - 1][j]
        trace[i][j] = (i - 1, j)
      elif f[i][j - 1] < f[i - 1][j] and f[i][j - 1] < f[i - 1][j - 1]:
        f[i][j] = f[i][j - 1]
        trace[i][j] = (i, j - 1)
      else:
        f[i][j] = f[i - 1][j - 1]
        trace[i][j] = (i - 1, j - 1)
      f[i][j] += dist(a[i], b[j])

  i, j = (m - 1, n - 1)
  path = []

  while not (i == -1):
    path.append((i, j))
    (i, j) = trace[i][j]

#  print "DTW dist = ", math.sqrt(f[m - 1][n - 1])
#  print "Path: ", path
#  valDist = 0
#  for i in range(len(path)):
#      valDist += dist(a[path[i][0]], b[path[i][1]])
#  print "Val dist = ", math.sqrt(valDist)
  return math.sqrt(f[m - 1][n - 1]), path

def plot_dtw(a, b, alabel, blabel, path, distance, offset=1):
  na = len(a)
  nb = len(b)

  xa = range(0, na)
  xb = np.arange(0, nb) + offset

  pairs = []
  path_x = []
  path_y = []
  for t in path:
    pairs.append([xa[t[0]], xb[t[1]]])
    pairs.append([a[t[0]], b[t[1]]])
    path_x.append(t[0])
    path_y.append(t[1])

  plt.plot(color='k', linestyle='--', linewidth=1, *pairs)
  plt.plot(xa, a, color='b', linestyle='-.', marker='o', linewidth=2, label=alabel)
  plt.plot(xb, b, color='r', linewidth=2, marker='x', label=blabel)
  plt.title('DTW distance = %.2f' % distance, fontsize=18)
  plt.legend(fontsize=13)


# A study on optimizing revenue from a website considered dividing customers into two groups based on a value x between 0 and 1,
# where x measures the proportion of the total bandwidth requested by a customer.
# Customers with a request less than x were considered low revenue, and those above x high revenue.
# The expected revenue from the low revenue customers was described by the following function,
# where C and k are positive constants based on attributes of the website and the customers.

import sympy as sp
import matplotlib.pyplot as plt
import numpy as np

domain_end = 20

g_xlim = [0, 40]
g_ylim = [0, 70]

# eq

x = sp.Symbol( 'x' )
C, k = sp.symbols( 'C k', positive = True )
R = C * k * ( 1 - np.e**( -k*x ) )
dR = diff( R, x )

lam_x = sp.lambdify( x, R, modules=[ "numpy", "sympy" ] )

x_vals = range = np.arange( 0.001, 1, 1/20.)
y_vals = lam_x( x_vals )


import numpy as np
import seaborn.apionly as sns
import matplotlib.pyplot as plt

sns.set(style="whitegrid", context="notebook")

iris2 = sns.load_dataset('iris')

def covariance(X, Y):
    xhat = np.mean(X)
    yhat = np.mean(Y)
    epsilon = 0
    for x, y in zip(X, Y):
        epsilon = epsilon + (x - xhat) * (y - yhat)
    return epsilon / (len(X) - 1)

# Testing results agains existing function
print("My covariance function: {}".format(covariance([1, 3, 4], [1, 0, 2])))
print("Numpy covariance function: {}".format(np.cov([1, 3, 4], [1, 0, 2])))

def correlation(X, Y):
    return (covariance(X, Y) / (np.std(X, ddof=1) * np.std(Y, ddof=1)))  # we had to indicat ddof=1 the unbiased std

print("My Correlation: {}".format(correlation([1, 1, 4, 3], [1, 0, 2, 2])))
print("Numpy corrcoef: {}".format(np.corrcoef([1, 1, 4, 3], [1, 0, 2, 2])))

# Start seeing a general view of the data to try to determine what is the best approach

sns.pairplot(iris2, height=3.0)
plt.show()
# Based on the results, we chose
X = iris2['petal_width']
Y = iris2['petal_length']

plt.scatter(X, Y)

# plt.show()

# Creating the prediction function
def predict(alpha, beta, x_i):
    return beta * x_i + alpha

# Defining the error function
def error(alpha, beta, x_i, y_i):  # L1
    return y_i - predict(alpha, beta, x_i)

def sum_sq_e(alpha, beta, x, y):  # L2
    return sum(error(alpha, beta, x_i, y_i) ** 2 for x_i, y_i in zip(x, y))

# Now we define a function implementing the correlation method to find the parameters for our regression
def correlation_fit(x, y):
    beta = correlation(x, y) * np.std(y, ddof=1) / np.std(x, ddof=1)
    alpha = np.mean(y) - beta * np.mean(x)
    return alpha, beta

alpha, beta = correlation_fit(X, Y)
print("Alpha: {}".format(alpha))
print("Beta: {}".format(beta))

plt.scatter(X, Y)
xr = np.arange(0, 3.5)
plt.plot(xr, (xr * beta) + alpha)
plt.show()


import colorsys
import numpy as np
from matplotlib import image

def pca(samples):
    """
    :param [in] samples: N-by-M matrix; each row is a M-dimensional sample
        NOTE: samples should be normalized: for every dimension, avg = 0 and std = 1
    :return (importance, newBases, newCoords)
        -   importance: M array; covar / importance of each new basis
        -   newBases: M-by-M matrix; each col is a new basis
        -   newCoords: N-by-M matrix; each row is the new coord of the original sample
                expressed with the new bases. A.k.a. score; loading
        NOTE: the original samples could be reconstructed as
                samples = newCoords * newBases.T
    """
    (sampleCount, coordLength) = samples.shape
    # NOTE: using "sample covar" here (divided by n-1 instead of n)
    covar = np.matmul(samples.T, samples).astype(np.double) / (sampleCount - 1)

    # Singular-value decomposition gives the eigenvalues (S), left-eigenvectors (U)
    # and right-eigenvectors (V)
    # since we put newBases on the right hand side of newCoords, we need the right-
    # eigenvectors
    U, S, VT = np.linalg.svd(covar)
    # col of V are principal directions
    V = VT.T

    # A eigenvalue represents the covar explained by this principal component
    # more ability to explain covar --> higher importance
    importance = S
    newBases = V
    newCoords = np.matmul(samples, V)

    return (importance, newBases, newCoords)

def loadGrayscaleImage(filename):
    img = image.imread(filename)

    # color image: (rows, cols, channels)
    if (len(img.shape) > 2):
        print("converting to grayscale")
        # convert to grayscale ("Y"/luma in YIQ)
        img = colorsys.rgb_to_yiq(r=img[:, :, 0], g=img[:, :, 1], b=img[:, :, 2])[0]
    return img


import matplotlib.pyplot as plt

import numpy as np

x = float(input("Enter the value of initial point(try 0.1): "))
y = float(input("Enter the value of final point(try 1.3): "))
n = int(input("number of intervals: "))

def simpson_third(x, y, n):
    h = (y - x) / n

    def fun(x):
        return 5 * x * np.exp(-2 * x)

    i = 0
    sum = 0
    #sum=fun(x)+fun(y)
    while i <= n:
        if i == 0:
            sum = sum + fun(x)
        elif i == n:
            sum = sum + fun(y)
        elif i % 2 == 0:
            sum = sum + 2 * fun(x + h * i)
        else:
            sum += 4 * fun(x + h * i)
        i += 1
    return (h / 3) * sum

from scipy.integrate import quad

def integrate(p):
    return 5 * p * np.exp(-2 * p)

exact_value = quad(integrate, 0.1, 1.3)
print(" The true value of integration is ", "%.5f" % exact_value[0])
result_38 = simpson_third(x, y, n)

print(" The value of integration is ", "%.5f" % result_38)

abs_err = ( result_38 - exact_value[0])

print(" error is: ",abs_err)

x = np.linspace(-5, 7, 40)
fun = 5 * x * (np.exp(-2 * x))
plt.plot(x, fun, 'g', label="5x exp(-2*x), range -5:5:40")
plt.xlabel("x")
plt.ylabel("Y")
plt.grid()
plt.title("f(x)= 5x exp(-2x)")
plt.savefig("Trapezoidal.png")
plt.show()


# 'coordinate_utility.py' contains a number of coordinate transformation functions.

import numpy as np

def spherical_2_cartesian(r, phi, theta, units='degrees'):
    """Converts spherical polar coordinates into cartesian coordinates.

    Parameters
    ----------
    r : array
        Radial distance.
    phi : array
        Longitudinal coordinates (radians = [0, 2*pi]).
    theta : array
        Latitude coordinates (radians = [0, pi]).
    units : str
        Units of phi and theta given in either degrees or radians.

    Returns
    -------
    x, y, z : array
        'euclidean': euclidean coordinates.
    """
    phi = np.copy(phi)
    theta = np.copy(theta)
    if units == 'degrees':
        phi, theta = np.deg2rad(phi), np.deg2rad(theta)
    elif units == 'radians':
        pass
    else:
        raise AssertionError("Unexpected value entered for 'units', only supports either degrees or radians", units)
    x = r * np.cos(phi) * np.sin(theta)
    y = r * np.sin(phi) * np.sin(theta)
    z = r * np.cos(theta)
    return x, y, z

def celestial_2_cartesian(r, ra, dec, units='degrees', output='both'):
    """Converts spherical polar coordinates into cartesian coordinates.

    Parameters
    ----------
    r : array
        Radial distance.
    ra : array
        Longitudinal celestial coordinates.
    dec : array
        Latitude celestial coordinates.
    units : str
        Units of ra and dec given in either degrees or radians.
    output : {'cartesian', 'both'}, optional
        Determines whether to output only the cartesian or both cartesian and spherical coordinates.

    Returns
    -------
    phi, theta : array
        'spherical': spherical polar coordinates.
    x, y, z : array
        'cartesian': euclidean coordinates.
    """
    phi = np.copy(ra)
    theta = np.copy(dec)
    if units == 'degrees':
        phi, theta = np.deg2rad(phi), np.deg2rad(theta)
    elif units == 'radians':
        pass
    else:
        raise AssertionError("Unexpected value entered for 'units', only supports either degrees or radians", units)
    theta = np.pi / 2. - theta
    if output == 'spherical':
        return phi, theta
    else:
        x = r * np.cos(phi) * np.sin(theta)
        y = r * np.sin(phi) * np.sin(theta)
        z = r * np.cos(theta)
        if output == 'cartesian':
            return x, y, z
        elif output == 'both':
            return phi, theta, x, y, z
        else:
            raise AssertionError("Unexpected value entered for 'output', should be either 'cartesian' or 'both'.",
                                 output)

def spherical_2_unit_sphere(phi, theta, units='degrees'):
    """Project coordinates on a sphere into cartesian coordinates on a unit sphere.

    Parameters
    ----------
    phi : array
        Longitudinal coordinates (radians = [0, 2*pi]).
    theta : array
        Latitude coordinates (radians = [0, pi]).
    units : {'degrees', 'radians'}, optional
        Units of phi and theta given in either 'degrees' or 'radians'.

    Returns
    -------
    x, y, z : array
        cartesian coordinates.
    """
    if np.isscalar(phi) is True:
        return spherical_2_cartesian(1., phi, theta, units=units)
    else:
        return spherical_2_cartesian(np.ones(len(phi)), phi, theta, units=units)

def celestial_2_unit_sphere(ra, dec, units='degrees', output='both'):
    """Project coordinates on a sphere into cartesian coordinates on a unit sphere.

    Parameters
    ----------
    ra : array
        Longitudinal celestial coordinates.
    dec : array
        Latitude celestial coordinates.
    units : {'degrees', 'radians'}, optional
        Units of ra and dec given in either 'degrees' or 'radians'.
    output : {'cartesian', 'both'}, optional
        Determines whether to output only the euclidean or both euclidean and spherical coordinates.

    Returns
    -------
    phi, theta : array
        'spherical': spherical polar coordinates.
    x, y, z : array
        'cartesian': cartesian coordinates.
    """
    if np.isscalar(ra) is True:
        return celestial_2_cartesian(1., ra, dec, units=units, output=output)
    else:
        return celestial_2_cartesian(np.ones(len(ra)), ra, dec, units=units, output=output)

def perpendicular_distance_2_angle(distance):
    """Converts distances on a unit sphere to angular distances projected across a unit sphere.

    Parameters
    ----------
    distance : array
        Perpendicular distances across (i.e. going on the surface) of a unit sphere.

    Returns
    -------
    angular_distance : array
        The angular distance of points across a unit sphere.
    """
    angular_distance = 2. * np.arcsin(distance / 2.)
    return angular_distance


import numpy as np
import matplotlib.pyplot as plt
import math
from KnotVectors import OpenUniformKnotVector, PeriodicKnotVector

def CoxDeBoorRecursion(i, order, Knots, t):
    if order == 1:
        return Knots[i] <= t and t < Knots[i + 1]
    else:
        ftt = (t - Knots[i]) * CoxDeBoorRecursion(i, order - 1, Knots, t)
        ftb = Knots[i + order - 1] - Knots[i]
        stt = (Knots[i + order] - t) * CoxDeBoorRecursion(i + 1, order - 1, Knots, t)
        stb = Knots[i + order] - Knots[i + 1]

        first = ftt / ftb
        if math.isnan(first):
            first = 0.

        second = stt / stb
        if math.isnan(second):
            second = 0.

        return first + second

def BasisGraph(Knots, order, i, T):
    values = []
    for t in T:
        values.append(CoxDeBoorRecursion(i, order, Knots, t))
    return np.asarray(values)

if __name__ == "__main__":
    order = 3
    countPoints = 4
    Knots = OpenUniformKnotVector(order, countPoints, True)

    T = np.arange(0., 1.0, 0.01)

    for i in range(countPoints):
        plt.plot(T, BasisGraph(Knots, order, i, T))

    plt.show()

    Knots = PeriodicKnotVector(order, countPoints, True)

    for i in range(countPoints):
        plt.plot(T, BasisGraph(Knots, order, i, T))

    plt.show()


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

np.seterr(all='raise')
factor = 2.0

class LinearModel(object):
    """Base class for linear models."""

    def __init__(self, theta=None):
        """
        Args:
            theta: Weights vector for the model.
        """
        self.theta = theta

    def fit(self, X, y):
        """Run solver to fit linear model. You have to update the value of
        self.theta using the normal equations.

        Args:
            X: Training example inputs. Shape (n_examples, dim).
            y: Training example labels. Shape (n_examples,).
        """
        #(X.TX)x = X.Ty
        a = np.dot(X.transpose(), X)
        b = np.dot(X.transpose(), y)
        self.theta = np.linalg.solve(a, b)

    def create_poly(self, k, X):
        """
        Generates a polynomial feature map using the data x.
        The polynomial map should have powers from 0 to k
        Output should be a numpy array whose shape is (n_examples, k+1)

        Args:
            X: Training example inputs. Shape (n_examples, 2).
        """
        polynomial = X[:, 0]
        for power in range(1 , k + 1):
            polynomial = np.column_stack((polynomial, np.power(X[:,1], power)))
        return polynomial

    def create_sin(self, k, X):
        """
        Generates a sin with polynomial featuremap to the data x.
        Output should be a numpy array whose shape is (n_examples, k+2)

        Args:
            X: Training example inputs. Shape (n_examples, 2).
        """
        polynomial = X[:, 0]
        for power in range(1 , k + 1):
            polynomial = np.column_stack((polynomial, np.power(X[:,1], power)))
        polynomial = np.column_stack((polynomial, np.sin(X[:,1])))
        return polynomial

    def predict(self, X):
        """
        Make a prediction given new inputs x.
        Returns the numpy array of the predictions.

        Args:
            X: Inputs of shape (n_examples, dim).

        Returns:
            Outputs of shape (n_examples,).
        """
        predictions = np.dot(X, self.theta)
        return predictions

def run_exp(train_path, sine=False, ks=[1, 2, 3, 5, 10, 20], filename='plot.png'):
    train_x, train_y=util.load_dataset(train_path,add_intercept=True)
    plot_x = np.ones([1000, 2])
    plot_x[:, 1] = np.linspace(-factor*np.pi, factor*np.pi, 1000)
    plt.figure()
    plt.scatter(train_x[:, 1], train_y)
    for k in ks:
        '''
        Our objective is to train models and perform predictions on plot_x data
        '''
        linearModel = LinearModel()
        if sine == True:
            polynomial = linearModel.create_sin(k, train_x)
        else:
            polynomial = linearModel.create_poly(k, train_x)
        linearModel.fit(polynomial, train_y)
        #Predictions
        if sine == True:
            polynomial = linearModel.create_sin(k, plot_x)
        else:
            polynomial = linearModel.create_poly(k, plot_x)
        plot_y = linearModel.predict(polynomial)
        '''
        Here plot_y are the predictions of the linear model on the plot_x data
        '''
        plt.ylim(-2, 2)
        plt.plot(plot_x[:, 1], plot_y, label='k=%d' % k)

    plt.legend()
    plt.savefig(filename)
    plt.clf()

def main(train_path, val_path):
    run_exp(train_path, sine=True, filename='train_sine.png')
    run_exp(train_path, sine=False, filename='train_poly.png')
    run_exp(val_path, sine=True, filename='eval_sine.png')
    run_exp(val_path, sine=False, filename='eval_poly.png')

if __name__ == '__main__':
    main(train_path='train.csv', val_path='valid.csv')


import numpy as np
import pandas as pd
import seaborn as sns
import scipy.stats as stats
import matplotlib.pyplot as plt

sns.set()

# This set option allow show more columns when you print the data
pd.set_option('display.max_columns', 100)

path = "nhanes_2015_2016.csv"

# First, you must import the data from the path given above
# using pandas, read in the csv data found at the url defined by 'path'
df = pd.read_csv(path)

# Next, look at the 'head' of our DataFrame 'df'.

# If you can't remember a function, open a previous notebook or video as a reference
# or use your favorite search engine to look for a solution

print("\nDataSet NHANES first 5 rows;\n",df.head(2))

# How many rows can you see when you don't put an argument into the previous method?
# How many rows can you see if you use an int as an argument?
# Can you use a float as an argument?

# Lets only consider the feature (or variable) 'BPXSY2'
bp = df['BPXSY2']

print("\nFeature BPXSY2:\n",bp)

# Numerical Summaries
# Find the mean (note this for the quiz that follows)

# What is the mean of 'BPXSY2'?
bp_mean = np.mean(bp)
print("\nMean of the feature BPXSY2:\n",bp_mean)
bp_mean2 = np.nanmean(bp)
print("\nMean2 of the feature BPXSY2:\n",bp_mean)
# In the method you used above, how are the rows of missing data treated?
# Are the excluded entirely? Are they counted as zeros? Something else?
# If you used a library function, try looking up the documentation using the code:
#
# help(function_you_used)
# For example:
# # help(np.sum)

##help(np.mean)

# .dropna()
# To make sure we know that we aren't treating missing data in ways we don't want,
# lets go ahead and drop all the nans from our Series 'bp'

bp = bp.dropna()
print("\nPrint BPXYS2 without NaN values:\n",bp)

# Find the:
# Median
# Max
# Min
# Standard deviation
# Variance
# You can implement any of these from base python (that is, without any of the imported packages),
# but there are simple and intuitively named functions in the numpy library for all of these.
# You could also use the fact that 'bp' is not just a list, but is a pandas.Series. You can find pandas.
# Series attributes and methods here

# A large part of programming is being able to find the functions you need and to understand
# the documentation formatting so that you can implement the code yourself, so we highly encourage
# you to search the internet whenever you are unsure!

# Example:
# Find the difference of an element in 'bp' compared with the previous element in 'bp'.

# Using the fact that 'bp' is a pd.Series object, can use the pd.Series method diff()
# call this method by: pd.Series.diff()
diff_by_series_method = bp.diff()
# note that this returns a pd.Series object, that is, it had an index associated with it
print("\npd.Series.diff() of bp data:\n",diff_by_series_method.values) # only want to see the values, not the index and values

# Now use the numpy library instead to find the same values
# np.diff(array)
diff_by_np_method = np.diff(bp)
print("\nnp.diff() of bp data:\n",diff_by_np_method)
# note that this returns an 'numpy.ndarray', which has no index associated with it, and therefore ignores
# the nan we get by the Series method

# We could also implement this ourselves with some looping
diff_by_me = [] # create an empty list
for i in range(len(bp.values)-1): # iterate through the index values of bp
    diff = bp.values[i+1] - bp.values[i] # find the difference between an element and the previous element
    diff_by_me.append(diff) # append to out list
print("\nDifference of bp data using looping:\n",np.array(diff_by_me)) # format as an np.array

# Your turn (note these values for the quiz that follows)

bp_median = np.median(bp)
print("\nMedian of bp data:\n",bp_median)

bp_max = np.max(bp)
print("\nMax of bp data:\n",bp_max)

bp_min = np.min(bp)
print("\nMin of bp data:\n",bp_min)

bp_std = np.std(bp)
print("\nStd of bp data:\n",bp_std)

bp_var = np.var(bp)
print("\nVar of bp data:\n",bp_var)

# How to find the interquartile range (note this value for the quiz that follows)
# This time we need to use the scipy.stats library that we imported above under the name 'stats'

bp_iqr = stats.iqr(bp)
print("\nInterquartil Range using Stats Library:\n",bp_iqr)

# Visualizing the data
# Next we'll use what you have learned from the Tables, Histograms, Boxplots in Python video

# use the Series.describe() method to see some descriptive statistics of our Series 'bp'
bp_descriptive_stats = bp.describe()
print("\nDescribe of bp data:\n",bp_descriptive_stats)

# Make a histogram of our 'bp' data using the seaborn library we imported as 'sns'
sns.displot(bp, kde = False)
plt.title("Histogram of BP Data")
plt.show()
# Is your histogram labeled and does it have a title? If not, try appending
# # .set(title='your_title', xlabel='your_x_label', ylabel='your_y_label')
# or just
# .set(title='your_title')
# to your graphing function

# Make a boxplot of our 'bp' data using the seaborn library. Make sure it has a title and labels!
sns.boxplot(data=bp).set_title("Box plot of the BP Data")
plt.show()

Understanding_and_Visualizing_Data_With_Python/Univariate Data/Python Assigment/Asssigment Week 2.py


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

#Numpy practice

#importing numpy

import numpy as np

# Create an array of 10 zeros

tza = np.zeros(10)

# Create an array of 10 ones

tna = np.ones(10)

 # Create an array of 10 Fives

tfa = np.ones(10) *5

# Create an array of integers from 10 - 50

aa = np.arange(10,51)

# Create a 3x3 matrix with values ranging from 0 to 8

ab = np.arange(9).reshape(3,3)

# Create a 3x3 Identity Matrix

ac = np.eye(3)

# Create a random number between 0 and 1

ad = np.random.rand(1)

# use numpy to generate an array of 25 random numbers from normal distribution

ae = np.random.randn(25)

# create a 10 by 10 matrix with values between 0 - 1

af = np.arange(0,100)/100
af.reshape(10,10)

# create an array of 20 linearly spacedpoints between 0 and 1

ag = np.linspace(0,1,20)

# matrix related operations

mat = np.arange(1,26).reshape(5,5)

#rows and columns selections within a matrix

#mat[2:,:]

# Sum of all values in a matrix

sumofmat = np.sum(mat)

# Get standard deviation of the values in mat

stdofmat = np.std(mat)

#get sum of all comlums in mat

sumofcolmat = mat.sum(axis = 0)