import sympy
import math
def gcd(a,b):
    if(b==0):
        return a
    else:
        return gcd(b,a%b)
def privatekey(x, y):
	def eea(a,b):
		if b == 0: return (1,0)
		(q,r) = (a//b,a%b)
		(s,t) = eea(b,r)
		return (t, s-(q*t))
	inv = eea(x,y)[0]
	if inv < 1 : inv += y
	return inv

def encrypt(message, pub_key,n):
	cypher_text= [(ord(char) ** pub_key) % n for char in message]
	return cypher_text
def decrypt(cypher_text:str,pri_key,n):
	plain_text = ''
	plain_text = [(char ** pri_key)%n for char in cypher_text]
	pt=[chr(plain) for plain in plain_text]
	plaintext=''.join(pt)
	return plaintext

def compute(v,p,q,e,m):
	message = {}
	if sympy.isprime(p):
		if sympy.isprime(q):
			n = p*q
			phiN=(p-1)*(q-1)
			# return phiN
			newgcd=gcd(phiN,e)
			if newgcd == 1:
				d 	= privatekey(e,phiN)
				if v==1:
					ctext = encrypt(m,e,n)
					ptext 	= decrypt(ctext,d,n)
					message = {
						'plain':ptext,
						'crypted':ctext,
						'privateKey':d,
						'phiN':phiN
					}
					return message
			else:
				message = {
						'msg':"Please choose e as 1<e<N",
					}
				return message
		else:
			message = {
				'msg': "Please enter Prime numbers"
			}
			return message
	else:
		message	=	{
			'msg':  "Please enter Prime numbers"
		}
		return message


import numpy as np
from matplotlib import pyplot as plt
from matplotlib import widgets as wg
from mpl_toolkits.mplot3d import Axes3D
from mayavi import mlab

import os
import zipfile
import urllib

def problem1():
    X = np.linspace(0, 2*np.pi, 400)
    Y1 = np.sin(X)
    Y2 = np.cos(X)
    plt.plot(X, Y1, "r--", X, Y2, "b:")
    plt.show()

def problem2():
    X1 = np.linspace(-2, 1-.01, 300)
    X2 = np.linspace(1.01, 6, 500)
    f = lambda X: 1./(X - 1)
    Y1 = f(X1)
    Y2 = f(X2)
    plt.plot(X1, Y1, 'm--', X2, Y2, 'm--', linewidth=5.0)
    plt.ylim((-6,6))
    plt.show()

def problem3():
    X = np.linspace(0, 10, 1001)
    Y = np.sin(X) / (X + 1)
    plt.plot(X, Y, ":")
    plt.fill_between(X, Y, where=Y>0, color='b')
    plt.fill_between(X, Y, where=Y<=0, color='r')
    plt.xlabel("x-axis")
    plt.ylabel("y-axis")
    plt.title("My Plot")
    plt.grid()
    indices = np.zeros_like(X, dtype=bool)
    for i in xrange(1, Y.size-1):
        if (Y[i-1]-Y[i])*(Y[i]-Y[i+1])<0:
            indices[i]=True
    plt.scatter(X[indices], .5*Y[indices], marker='^')
    plt.xlim((0,10))
    plt.show()

def problem4():
    R = np.linspace(0, 2, 401)
    I = R.copy()
    R, I = np.meshgrid(R, I)
    X = R + complex(0,1)*I
    f = np.poly1d([1, 2, -1, 3])
    Y = np.absolute(f(X))
    plt.pcolormesh(R, I, Y)
    plt.show()

def problem5():
    fig = plt.figure()
    ax = fig.gca(projection='3d')
    x = np.linspace(-10, 10, 501)
    y = np.linspace(-10, 10, 501)
    x, y = np.meshgrid(x, y)
    d = np.sqrt(x**2 + y**2)
    z = np.cos(d) / (.1 * d**2 + 1)
    ax.plot_surface(x, y, z)
    plt.show()

def problem6():
    ax = plt.subplot(111)
    plt.subplots_adjust(bottom=.25)
    t = np.arange(0, 1.01, .01)
    a = 5.
    f = 3.
    p = 0.
    fc = lambda a, f, p, t: a * np.sin(2*np.pi*f*(t-p))
    l = plt.plot(t, fc(a, f, p, t))[0]
    axfreq = plt.axes([.25, .05, .65, .03])
    axamp = plt.axes([.25, .1, .65, .03])
    axph = plt.axes([.25, .15, .65, .03])
    sfreq = wg.Slider(axfreq, "Freq", .1, 30., valinit=f)
    samp = wg.Slider(axamp, "Amp", .1, 10., valinit=a)
    sph = wg.Slider(axph, "Phase", 0, 2*np.pi, valinit=p)
    def update(val):
        a = samp.val
        f = sfreq.val
        p = sph.val
        l.set_ydata(fc(a,f,p,t))
        plt.draw()
    sfreq.on_changed(update)
    samp.on_changed(update)
    sph.on_changed(update)
    plt.show()

def problem7():
    x = np.linspace(-3,3)
    plt.subplot(221)
    plt.plot(x, np.exp(x))
    plt.subplot(222)
    plt.plot(x, np.sin(x))
    plt.subplot(223)
    plt.plot(x, np.cos(x))
    plt.subplot(224)
    plt.plot(x, x**2)
    plt.suptitle("My Different Plots")
    plt.show()

def problem8():
    opener = urllib.URLopener()
    opener.retrieve('https://s3.amazonaws.com/storage.enthought.com/www/sample_data/N36W113.hgt.zip', 'N36W113.hgt.zip')
    data = np.fromstring(zipfile.ZipFile('N36W113.hgt.zip').read('N36W113.hgt'), '>i2').reshape((3601, 3601)).astype('float32')
    data = data[:1000, 900:1900]
    data[data == -32768] = data[data>0].min()
    mlab.figure(size=(400, 320), bgcolor = (.16, .28, .46))
    mlab.surf(data, colormap="gist_earth", warp_scale=.2, vmin=1200, vmax=1610)
    mlab.view(-5.9, 83, 570, [5.3, 20, 238])
    return mlab.gcf()


import numpy as np
from matplotlib import image
from matplotlib import pyplot
import timeit

# showing image using matplotlib images

image = image.imread('img/fig-ndarray-array-indexing-copy.png')
# printing image dtype
print(image.dtype)
# printing image shape
print(image.shape)
# display the array of pixels as an image
pyplot.imshow(image)
pyplot.show()

# numpy slicing and data sharing
x = np.arange(15, dtype=np.float32).reshape(3,5)
y  = x[:2,2:4].T
y[:] = -y
z = y.copy()
# this can also be done as
z2 = np.copy(y, order='C')

# Using Numpy to vectorize code
# x is 2-dimensional ndarray of numbers
def funct1(x):
    n, m = x.shape
    v = x[0, 0]
    for i in range(n):
        for j in range(m):
            if x[i, j] < v:
                v = x[i, j]

    y = np.empty_like(x)
    for i in range(n):
        for j in range(m):
            y[i, j] = x[i, j] - v

    return y

# we can do the same function as a vectorized numpy function

def funct1_vectorized(x):
    return x - x.min()

# testing these functions:
x = np.random.randint(1000, size=(200,200))
time_loop = timeit.timeit('funct1(x)',      setup="from __main__ import funct1, x", number=10)
vect_time_loop = timeit.timeit('funct1_vectorized(x)', setup="from __main__ import funct1_vectorized, x", number=10)

print("On a 200*200 matrix, Funct1 ran at: {:.1} and funct1_vectorized ran at: {:.1}. Therefore, the vectorized function ran {:.1} faster".format(time_loop, vect_time_loop,(time_loop/vect_time_loop)))

# check linear system solution quality

# Suppose you are given matrix  𝐴∈ℝ𝑚×𝑛  and vector  𝑏∈ℝ𝑚  and are told that  𝑥∈ℝ𝑛  is a solution to the system of linear equations  𝐴𝑥=𝑏 .
def is_solution(A, b, x, epsilon=1e-5):
    """Returns whether x is a solution to Ax=b, with all residuals below epsilon."""
    return np.abs(A @ x - b).max() < epsilon

A = np.array([[2., 0.5], [-5., 3.]])
b = np.array([5., 9.])
x = np.array([1.23529, 5.05882])
result = is_solution(A, b, x)
print(result)

# Shuffling pair of matrices together
# Suppose you are given a pair of matrices  𝑋∈ℝ𝑚×𝑛  and  𝑌∈ℝ𝑚×𝑘 , and you must 'shuffle' their rows by the same permutation.


#
# sine_wave.py
# Animate a sine wave and save it as MP4 file
# Sparisoma Viridi | https://github.com/dudung/cookbook
# 20220331 Create this program by modifying original one [1].
#
# 1. marlise23, "Python unknown file extension .mp4",
#    Stack Overflow, 20 Oct 2019,
#    url https://stackoverflow.com/q/58469357/9475509
#    [20220331].
#

# url https://realpython.com/python-import/
# Make code in one module available in anothe
import numpy as np

# url https://www.w3schools.com/python/ref_keyword_from.asp
# Import only certain section from a module
from matplotlib import pyplot as plt
from matplotlib import animation

# url https://matplotlib.org/3.5.1/api/_as_gen/matplotlib.pyplot.figure.html
# Create a new figure, or activate an existing figure
fig = plt.figure()

# url https://matplotlib.org/3.5.0/api/_as_gen/matplotlib.pyplot.axes.html
# Add an axes to the current figure and make it the current axes
ax = plt.axes(xlim=(0, 2), ylim=(-2, 2))

# url https://matplotlib.org/3.5.0/api/_as_gen/matplotlib.axes.Axes.plot.html
# Plot y versus x as lines and/or markers
line, = ax.plot([], [], lw=2)

# url https://stackoverflow.com/q/58469357/9475509
# Initialize each frame by plotting the background
def init():
  # url https://matplotlib.org/3.5.0/api/_as_gen/matplotlib.lines.Line2D.html#matplotlib.lines.Line2D.set_data
	# Set the x and y data
  line.set_data([], [])
  return line,

# url https://stackoverflow.com/q/58469357/9475509
# Call sequentially plotted function
def animate(i):
  # url https://numpy.org/doc/stable/reference/generated/numpy.linspace.html
	# Return evenly spaced numbers over a specified interval
  x = np.linspace(0, 2, 1000)

  # url https://numpy.org/doc/stable/reference/generated/numpy.sin.html
  # Trigonometric sine, element-wise
  y = np.sin(2 * np.pi * (x - 0.01 * i))

  # url https://matplotlib.org/3.5.0/api/_as_gen/matplotlib.lines.Line2D.html#matplotlib.lines.Line2D.set_data
  line.set_data(x, y)
  return line,

# url https://matplotlib.org/3.5.1/api/_as_gen/matplotlib.animation.FuncAnimation.html
# Makes an animation by repeatedly calling a function func
anim = animation.FuncAnimation(fig, animate, init_func=init, frames=200, interval=20, blit=True)

# url https://matplotlib.org/2.0.2/api/_as_gen/matplotlib.animation.Animation.save.html
# Saves a movie file by drawing every frame
anim.save('sine_wave_animation.mp4', fps=30, extra_args=['-vcodec', 'libx264'])

# url https://matplotlib.org/3.5.0/api/_as_gen/matplotlib.pyplot.show.html
# Display all open figures
plt.show()


import sys
import os
import numpy as np
from scipy import signal
import math
import random
import cv2
import run

def make_gaussian(k, std):
  '''Create a gaussian kernel.

  Input:

  k - the radius of the kernel.

  std - the standard deviation of the kernel.

  Output:

  output - a numpy array of shape (2k+1, 2k+1) and dtype float.

  If gaussian_1d is a gaussian filter of length 2k+1 in one dimension,
  kernel[i,j] should be filled with the product of gaussian_1d[i] and
  gaussian_1d[j].

  Once all the points are filled, the kernel should be scaled so that the sum
  of all cells is equal to one.'''
  kernel = None
  # Insert your code here.----------------------------------------------------
  kernel=np.zeros((2*k+1,2*k+1),dtype=np.float)
  gaussian_1d = signal.gaussian(2*k+1,std)
  for i in range(gaussian_1d.shape[0]):
    for j in range(gaussian_1d.shape[0]):
      kernel[i,j]=gaussian_1d[i]*gaussian_1d[j]
  kernelsum = kernel.sum()
  kernel = kernel/kernelsum
  #---------------------------------------------------------------------------
  return kernel

def test():
  '''This script will perform a unit test on your function, and provide useful
  output.
  '''

  np.set_printoptions(precision=3)

  ks =  [1, 2, 1, 2, 1]
  sds = [1, 2, 3, 4, 5]
  outputs = []
  # 1,1
  y = np.array([[ 0.075,  0.124,  0.075],
             [ 0.124,  0.204,  0.124],
             [ 0.075,  0.124,  0.075]])
  outputs.append(y)
  # 2,2
  y = np.array([[ 0.023,  0.034,  0.038,  0.034,  0.023],
             [ 0.034,  0.049,  0.056,  0.049,  0.034],
             [ 0.038,  0.056,  0.063,  0.056,  0.038],
             [ 0.034,  0.049,  0.056,  0.049,  0.034],
             [ 0.023,  0.034,  0.038,  0.034,  0.023]])
  outputs.append(y)
  # 1,3
  y = np.array([[ 0.107,  0.113,  0.107],
             [ 0.113,  0.120,  0.113],
             [ 0.107,  0.113,  0.107]])
  outputs.append(y)
  # 2,4
  y = np.array([[ 0.035,  0.039,  0.04 ,  0.039,  0.035],
             [ 0.039,  0.042,  0.044,  0.042,  0.039],
             [ 0.04 ,  0.044,  0.045,  0.044,  0.04 ],
             [ 0.039,  0.042,  0.044,  0.042,  0.039],
             [ 0.035,  0.039,  0.04 ,  0.039,  0.035]])
  outputs.append(y)
  # 1,5
  y = np.array([[ 0.11 ,  0.112,  0.11 ],
             [ 0.112,  0.114,  0.112],
             [ 0.11 ,  0.112,  0.11 ]])
  outputs.append(y)

  for k, sd, output in zip(ks, sds, outputs):
    if __name__ == "__main__":
      print "k:{}, sd:{}".format(k, sd)

    usr_out = make_gaussian(k, sd)

    if not type(usr_out) == type(output):
      if __name__ == "__main__":
        print "Error- output has type {}. Expected type is {}.".format(
            type(usr_out), type(output))
      return False

    if not usr_out.shape == output.shape:
      if __name__ == "__main__":
        print "Error- output has shape {}. Expected shape is {}.".format(
            usr_out.shape, output.shape)
      return False

    if not usr_out.dtype == output.dtype:
      if __name__ == "__main__":
        print "Error- output has dtype {}. Expected dtype is {}.".format(
            usr_out.dtype, output.dtype)
      return False

    if not np.all(np.abs(usr_out - output) < .005):
      if __name__ == "__main__":
        print "Error- output has value:\n{}\nExpected value:\n{}".format(
            usr_out, output)
      return False

    if __name__ == "__main__":
      print "Passed."

  if __name__ == "__main__":
    print "Success."
  return True

if __name__ == "__main__":
  # Testing code
  print "Performing unit test. Tests will be accepted if they are within .005 \
of the correct answer."
  test()


from numpy import *
from matplotlib.pyplot import *

def A_exact(F, p):
    return exp(-4*F*p**2)

def A_FE(F, p):
    return 1 - 4*F*sin(p)**2

def A_BE(F, p):
    return 1/(1 + 4*F*sin(p)**2)

def A_CN(F, p):
    return (1 - 2*F*sin(p)**2)/(1 + 2*F*sin(p)**2)

def compare_plot(F, p):
    figure()
    plot(p, A_BE(F, p),
         p, A_exact(F, p),
         p, A_CN(F, p),
         p, A_FE(F, p),)
    legend(['BE', 'exact', 'CN', 'FE'])
    title('F=%g' % F)
    print('F:', F)
    if 0.2 >= F > 0.02:
        axis([p[0], p[-1], 0.3, 1])
    elif F <= 0.02:
        axis([p[0], p[-1], 0.75, 1])
    else:
        axis([p[0], p[-1], -1.2, 1])
    xlabel('$p=k\Delta x$')
    ylabel('$A(p)$')
    savefig('A_F%s.pdf' % (str(F).replace('.', '')))
    savefig('A_F%s.png' % (str(F).replace('.', '')))

p = linspace(0, pi/2, 101)
for F in 20, 5, 2, 0.5, 0.25, 0.1, 0.01:
    compare_plot(F, p)
'''
#import sys; sys.exit(0)
from sympy import *
F, p, dx, dt, k = symbols('F p dx dt k')
A_err_FE = A_exact(F, p) - A_FE(F, p)
A_err_FE = A_FE(F, p)/A_exact(F, p)
#print 'Error in A, FE:', A_err_FE.series(F, 0, 6)
A_err_FE = A_err_FE.subs(F, dt/dx**2).subs(sin(p), 1).subs(p, k*dx/2)
print 'Error in A, FE:', A_err_FE.series(dt, 0, 3)
print latex(A_err_FE.series(F, 0, 6))
A_err_BE = A_exact(F, p) - A_BE(F, p)
A_err_BE = A_BE(F, p)/A_exact(F, p)
print 'Error in A, BE:', A_err_BE.series(F, 0, 6)
print latex(A_err_BE.series(F, 0, 6))
A_err_CN = A_exact(F, p) - A_CN(F, p)
A_err_CN = A_CN(F, p)/A_exact(F, p)
print 'Error in A, CN:', A_err_CN.series(F, 0, 6)
print latex(A_err_CN.series(F, 0, 6))
'''
input()

show()

f = open('tmp.sh', 'w')
f.write("""#!/bin/sh
doconce combine_images A_F20.pdf A_F2.pdf diffusion_A_F20_F2.pdf
doconce combine_images A_F20.png A_F2.png diffusion_A_F20_F2.png

doconce combine_images A_F05.png A_F025.png diffusion_A_F05_F025.png
doconce combine_images A_F05.pdf A_F025.pdf diffusion_A_F05_F025.pdf

doconce combine_images A_F01.pdf A_F001.pdf diffusion_A_F01_F001.pdf
doconce combine_images A_F01.png A_F001.png diffusion_A_F01_F001.png
""")
f.close()
import os
os.system('sh -x tmp.sh')


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

import matplotlib.pyplot as plt
import numpy as np

def gaussianFunction(x, mu, sigma):
    """[summary]
    Calculates the value of the gaussian function in the point x.
    Args:
        x (array): [Vector of x values]
        mu (int): [Mean of the gaussian function]
        sigma (int): [Standard deviation of the gaussian function]
    Returns:
        [float]: [Value of the gaussian function]
    """
    return np.exp(-(x - mu)**2 / (2 * sigma**2))

if __name__ == "__main__":
    # Generate a normal distribution with mean 0 and standard deviation 1
    mu, sigma = 0, 1
    x = np.linspace(-5, 5, 100)
    y = gaussianFunction(x, mu, sigma)

    # Graficamos
    plt.plot(x, y, 'b--')
    plt.xlabel('X Axis')
    plt.ylabel('Y Axis')
    plt.title('Gaussian Function for range [-5, 5]')
    plt.savefig('Clase_02/Docs/GaussianFunction.png', dpi=300)
    plt.show()


import numpy as np

'''
------------------------------------------------
Use dynamic programming (DP) to solve 0/1 knapsack problem
Time complexity: O(nW), where n is number of items and W is capacity

Author: Kaiyang Zhou
Website: https://kaiyangzhou.github.io/
------------------------------------------------
knapsack_dp(values,weights,n_items,capacity,return_all=False)

Input arguments:
  1. values: a list of numbers in either int or float, specifying the values of items
  2. weights: a list of int numbers specifying weights of items
  3. n_items: an int number indicating number of items
  4. capacity: an int number indicating the knapsack capacity
  5. return_all: whether return all info, defaulty is False (optional)

Return:
  1. picks: a list of numbers storing the positions of selected items
  2. max_val: maximum value (optional)
------------------------------------------------
'''
def knapsack_dp(values,weights,n_items,capacity,return_all=False):
    check_inputs(values,weights,n_items,capacity)

    table = np.zeros((n_items+1,capacity+1),dtype=np.float32)
    keep = np.zeros((n_items+1,capacity+1),dtype=np.float32)

    for i in range(1, n_items + 1):
        for w in range(0, capacity + 1):
            wi = weights[i-1] # weight of current item
            vi = values[i-1] # value of current item
            if (wi <= w) and (vi + table[i-1,w-wi] > table[i-1,w]):
                table[i,w] = vi + table[i-1,w-wi]
                keep[i,w] = 1
            else:
                table[i,w] = table[i-1,w]

    picks = []
    K = capacity

    for i in range(n_items, 0, -1):
        if keep[i,K] == 1:
            picks.append(i)
            K -= weights[i-1]

    picks.sort()
    picks = [x-1 for x in picks] # change to 0-index

    if return_all:
        max_val = table[n_items,capacity]
        return picks,max_val
    return picks

def check_inputs(values,weights,n_items,capacity):
    # check variable type
    assert(isinstance(values,list))
    assert(isinstance(weights,list))
    assert(isinstance(n_items,int))
    assert(isinstance(capacity,int))
    # check value type
    assert(all(isinstance(val,int) or isinstance(val,float) for val in values))
    assert(all(isinstance(val,int) for val in weights))
    # check validity of value
    assert(all(val >= 0 for val in weights))
    assert(n_items > 0)
    assert(capacity > 0)

if __name__ == '__main__':
    values = [2,3,4]
    weights = [1,2,3]
    n_items = 3
    capacity = 3
    picks = knapsack_dp(values,weights,n_items,capacity)
    print(picks)


'''Welcome to the data visualization section of the course!

This file contains functions for you to implement that will produce various plots.

As data visualization is somewhat subjective, it is not possible to write functions
that test exactly what you code does for most of this script.
Instead, there is a folder in this directory titled ('Instructor Visualizations') that
will give you an idea of what your final visualization should look like.

Don't forget, the TAs are available on Piazza and during office hours if you need help,
have questions, or have feedback about the course.
Good luck, and have fun!
'''

import pandas as pd
import scipy.stats
from plotnine import ggplot, aes, geom_point, ggtitle

from test import test_mean, test_regression

def calculate_mean(data):
    '''This function will calculate the mean values of the provided dataset.

    Inputs
    ------
    data: list of ints
        The points to calculate the mean of

    Returns
    -------
    mean: float
        The mean of all the values passed in
    '''

    mean = float(sum(data)) / len(data)

    return mean

def calculate_regression_coeff(x, y):
    '''Calculate the linear regression coefficients (slope and intercept) for given x and y values
    Hint: The stats.linregress function from scipy may be useful here

    Inputs
    ------
    x: list of ints
        The set of x-values for the points
    y: list of ints
        The set of y-values for the points

    Returns
    -------
    slope:
        The linear regression coefficient measuring the correlation between x and y
    intercept:
        The regression coefficient measuring where the regression line hits the y axis
    '''
    regression = scipy.stats.linregress(x, y)
    slope = regression.slope
    intercept = regression.intercept

    return slope, intercept

def describe_data():
    '''There is something unusual about this set of x-y coordinates.
    Figure out what it is by calculating the x means, y means and running linear regresion.
    Finally, plot the points and see if the data looks like you expected.
    '''
    x1 = [10, 8, 13, 9, 11, 14, 6, 4, 12, 7, 5]
    y1 = [8.04, 6.95, 7.58, 8.81, 8.33, 9.96, 7.24, 4.26, 10.84, 4.82, 5.68]

    x2 = [10, 8, 13, 9, 11, 14, 6, 4, 12, 7, 5]
    y2 = [9.14, 8.14, 8.74, 8.77, 9.26, 8.10, 6.13, 3.10, 9.13, 7.26, 4.74]

    x3 = [10, 8, 13, 9, 11, 14, 6, 4, 12, 7, 5]
    y3 = [7.46, 6.77, 12.74, 7.11, 7.81, 8.84, 6.08, 5.39, 8.15, 6.42, 5.73]

    x4 = [8, 8, 8, 8, 8, 8, 8, 19, 8, 8, 8]
    y4 = [6.58, 5.76, 7.71, 8.84, 8.47, 7.04, 5.25, 12.50, 5.56, 7.91, 6.89]

    print(calculate_mean(x1))
    print(calculate_mean(x2))
    print(calculate_mean(x3))
    print(calculate_mean(x4))

    print(calculate_mean(y1))
    print(calculate_mean(y2))
    print(calculate_mean(y3))
    print(calculate_mean(y4))

    print(calculate_regression_coeff(x1, y1))
    print(calculate_regression_coeff(x2, y2))
    print(calculate_regression_coeff(x3, y3))
    print(calculate_regression_coeff(x4, y4))

    df = pd.DataFrame({'x1': x1, 'y1':y1,
                       'x2': x2, 'y2':y2,
                       'x3': x3, 'y3':y3,
                       'x4': x4, 'y4':y4}
                     )

    print(ggplot(df, aes(x='x1', y='y1')) + geom_point())
    print(ggplot(df, aes(x='x2', y='y2')) + geom_point())
    print(ggplot(df, aes(x='x3', y='y3')) + geom_point())
    print(ggplot(df, aes(x='x4', y='y4')) + geom_point())

    test_mean(x1, calculate_mean(x1))
    test_mean(x2, calculate_mean(x2))
    test_mean(x3, calculate_mean(x3))
    test_mean(x4, calculate_mean(x4))
    test_mean(y1, calculate_mean(y1))
    test_mean(y2, calculate_mean(y2))
    test_mean(y3, calculate_mean(y3))
    test_mean(y4, calculate_mean(y4))
    test_regression(x1, y1, *calculate_regression_coeff(x1, y1))
    test_regression(x2, y2, *calculate_regression_coeff(x2, y2))
    test_regression(x3, y3, *calculate_regression_coeff(x3, y3))
    test_regression(x4, y4, *calculate_regression_coeff(x4, y4))

if __name__ == '__main__':
    describe_data()


r"""Implementation of the log-sum-exp trick.

The goal is to calculate \log\sum_{i}e^{x_{i}} in a numeric
stable manner.
"""
import typing as t

import numpy as np

def log_sum_exp(vals: np.ndarray,
                shift_coeff: t.Optional[t.Union[int, float]] = None) -> float:
    r"""Calculate \log_{e}\sum_{i}e^{vals_{i}} in a numeric stable manner."""
    if shift_coeff is None:
        shift_coeff = np.max(vals)

    if np.isinf(shift_coeff):
        return np.inf

    return shift_coeff + np.log(np.sum(np.exp(vals - shift_coeff)))

def _test():
    import scipy.special

    np.random.seed(16)
    for _ in np.arange(1024):
        size = np.random.randint(2, 16384)
        vals = np.random.randint(
            -1e+16, 1e+16, size=size) + np.random.random(size=size)
        assert np.allclose(log_sum_exp(vals), scipy.special.logsumexp(vals))

if __name__ == "__main__":
    _test()


import numpy as np

def print_matrix(mat):
    for line in mat:
        print('  '.join(map(str, line)))
    print()

def input_matrix(matrix, n):
    return np.reshape(matrix, (n, n))

def read_data_from_txt_file(filename):
    file = open(filename, "r")
    tmp = file.readlines()
    TMPdata = []
    for line in tmp:
        TMPdata.append(int(line.strip()))
    return TMPdata

def conditional(mat, norm):
    inv = np.linalg.inv(np.array(mat))
    if norm == "fro":
        print(f"A norm:{norm} = {np.linalg.norm(mat, 'fro')}\nA^-1 norm:{norm} = {np.linalg.norm(inv, 'fro')}")
        return np.linalg.norm(mat, "fro") * np.linalg.norm(inv, "fro")

    if norm == "nuc":
        print(f"A norm:{norm} = {np.linalg.norm(mat, 'nuc')}\nA^-1 norm:{norm} = {np.linalg.norm(inv, 'nuc')}")
        return np.linalg.norm(mat, "nuc") * np.linalg.norm(inv, "nuc")

    if norm == "inf":
        print(f"A norm:{norm} = {np.linalg.norm(mat, np.inf)}\nA^-1 norm:{norm} = {np.linalg.norm(inv, np.inf)}")
        return np.linalg.norm(mat, np.inf) * np.linalg.norm(inv, np.inf)

    if norm == "-inf":
        print(f"A norm:{norm} = {np.linalg.norm(mat, -np.inf)}\nA^-1 norm:{norm} = {np.linalg.norm(inv, -np.inf)}")
        return np.linalg.norm(mat, -np.inf) * np.linalg.norm(inv, -np.inf)

    if norm == "1":
        print(f"A norm:{norm} = {np.linalg.norm(mat, 1)}\nA^-1 norm:{norm} = {np.linalg.norm(inv, 1)}")
        return np.linalg.norm(mat, 1) * np.linalg.norm(inv, 1)

    if norm == "-1":
        print(f"A norm:{norm} = {np.linalg.norm(mat, -1)}\nA^-1 norm:{norm} = {np.linalg.norm(inv, -1)}")
        return np.linalg.norm(mat, -1) * np.linalg.norm(inv, -1)

    if norm == "2":
        print(f"A norm:{norm} = {np.linalg.norm(mat, 2)}\nA^-1 norm:{norm} = {np.linalg.norm(inv, 2)}")
        return np.linalg.norm(mat, 2) * np.linalg.norm(inv, 2)

    if norm == "-2":
        print(f"A norm:{norm} = {np.linalg.norm(mat, -2)}\nA^-1 norm:{norm} = {np.linalg.norm(inv, -2)}")
        return np.linalg.norm(mat, -2) * np.linalg.norm(inv, -2)
    return "Error"

data = read_data_from_txt_file("data.txt")
A = input_matrix(data, int(np.sqrt(len(data))))
A_inv = np.linalg.inv(A)
print_matrix(A_inv)
B = np.array([1 for i in range(int(np.sqrt(len(data))))])
X = np.linalg.inv(A).dot(B)
print_matrix(A)
eig = np.linalg.eig(A.dot(A.transpose()))
print(eig)
print(X)
t = np.array([[65, 28], [28, 32]])
print_matrix(t)
norm = '2'
print(f"cond(A){norm}={conditional(A, norm)}")


from scipy.stats import chisquare

# can we assume anything from our sample
significance = 0.05

# what do we expect to see in proportions?
expected_proportions = [.05, .1, .15, .7]

# what counts did we see in our sample?
observed_counts = [27, 73, 82, 468]

########################
# how big was our sample
sample_size = sum(observed_counts)

# we derive our comparison counts here for  our expected proportions, based on the sample size
expected_counts = [float(sample_size) * x for x in expected_proportions]

# Get the stat data
(chi_stat, p_value) = chisquare(observed_counts, expected_counts)

# report
print('chi_stat: %0.5f, p_value: %0.5f' % (chi_stat, p_value))

if p_value > significance:
    print("Fail to reject the null hypothesis - we have nothing else to say")
else:
    print("Reject the null hypothesis - suggest the alternative hypothesis is true")


# This program describes matrices and their Operations
# This function introduces various ways to create
# matrices and how to use them in TensorFlow

import numpy as np
import tensorflow as tf
from tensorflow.python.framework import ops
ops.reset_default_graph()

# Define a session
sess = tf.Session()

# Define Identity Matrix
A_identity_matrix = tf.diag([1.0,1.0,1.0])
print(sess.run(A_identity_matrix))

# Create a 3x3 Random Norm Matrix
A_matrix = tf.truncated_normal([3,3])
print(sess.run(A_matrix))

# Create a 3x2 Constant Matrix, 7.0 is the Constant Value
A_const_matrix = tf.fill([3,2], 7.0)
print(sess.run(A_const_matrix))

# Calculate a Matrix Multiplication
print(sess.run(tf.matmul(A_matrix, A_const_matrix)))

# Create 4x4 Random Uniform Matrix
A_rand_matrix = tf.random_uniform([4,4])
print(sess.run(A_rand_matrix))

# Create a Matrix From a np Array
ATensor_from_array = tf.convert_to_tensor(np.array([[12.7, 21.5, 13.2], [-3.3, -17.2, -11.3], [0.1, 5.1, -2.7]]))
print(sess.run(ATensor_from_array))

# Calculate Matrix Addition and Subtraction
print(sess.run(A_identity_matrix+A_matrix))
print(sess.run(A_identity_matrix-A_matrix))

# Calculate Matrix Transpose
print(sess.run(tf.transpose(A_const_matrix)))

# Calculate Matrix Determinant
print(sess.run(tf.matrix_determinant(A_rand_matrix)))

# Calculate Another Matrix Multiplication
print(sess.run(tf.matmul(A_matrix, A_identity_matrix)))

# Calculate Matrix Inverse
print(sess.run(tf.matrix_inverse(A_rand_matrix)))
print(sess.run(tf.matrix_inverse(A_matrix)))

# Calculate Eigenvalues and Eigenvectors
print(sess.run(tf.self_adjoint_eig(A_rand_matrix)))
print(sess.run(tf.self_adjoint_eig(A_matrix)))


import numpy as np

class Activation:
    def step_function(self,x):
        y = x > 0
        return y.astype(np.int)

    #왜 sigmoid?
    # 출력이 0~1 사이이고, 미분이 쉬운 함수들중 가장 그럴듯 해서 많이 사용하게됨. 미분은 exp이 쉽기때문에
    def sigmoid(self,x):
        return 1/(1 + np.exp(-x))

    def RelU(self,x):
        return np.maximum(0,x)

     #왜 softmax?
    # 출력이 0~1 사이이고, 미분이 쉬운 함수들중 가장 그럴듯 해서 많이 사용하게됨. 미분은 exp이 쉽기때문에
    def softmax(self,xs):
        if xs.ndim == 2:
            xs = xs.T
            xs = xs - np.max(xs, axis=0)
            y = np.exp(xs) / np.sum(np.exp(xs), axis=0)
            return y.T

        xs = xs - np.max(xs) # 오버플로 대책
        return np.exp(xs) / np.sum(np.exp(xs))

class LossFun:
    def MSE(self,ts,ys):
        batch_size = ys.shape[0]
        if ys.ndim == 1:
            ts = ts.reshape(1,ts.size)
            ys = ys.reshape(1,ys.size)
        return 1/2*(np.sum((ys - ts)**2))  / batch_size

    #def CEE(self,ts,ys,IsOneHot = True):
    #    batch_size = ys.shape[0]
    #    if ys.ndim == 1:
    #        ts = ts.reshape(1,ts.size)
    #        ys = ys.reshape(1,ys.size)
    #
    #    if IsOneHot :
    #         return -np.sum(ts*np.log(ys + 1e-7) ) / batch_size
    #    else:
    #         return -np.sum(np.log(ys[np.arange(batch_size) , ts] + 1e-7) ) / batch_size

    def CEE(self,ts,ys):
        batch_size = ys.shape[0]

        if ys.ndim == 1:
            ts = ts.reshape(1,ts.size)
            ys = ys.reshape(1,ys.size)

        if ts.size == ys.size:
            ts = ts.argmax(axis=1)

        return -np.sum(np.log(ys[np.arange(batch_size), ts])) / batch_size

class Diff:
    def NGradient(self,f,x):
        h = 1e-4 # 0.0001
        grad = np.zeros_like(x)

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

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

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

        return grad

    def diff(self,f,x):
        h = 1e-4
        return (f(x+h)-f(x-h)) / (2*h)

    def gradient(self,f,x):
        h = 1e-4
        grad = np.zeros_like(x)

        for idx in range(x.size):
            tmpVal = x[idx]

            x[idx] = tmpVal + h
            fxh1 = f(x)

            x[idx] = tmpVal - h
            fxh2 = f(x)

            grad[idx] = (fxh1 - fxh2) / (2*h)
            x[idx] = tmpVal
        return grad

    def diff_Line(self,a,x0,y0,x):
        return a*(x - x0)+y0

class SGD:
    def NGradient(self,f,s):
        h = 1e-4 # 0.0001
        grad = np.zeros_like(x)

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

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

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

        return grad

    def gradient(self,f,x):
        h = 1e-4
        grad = np.zeros_like(x)

        for idx in range(x.size):
            tmpVal = x[idx]

            x[idx] = tmpVal + h
            fxh1 = f(x)

            x[idx] = tmpVal - h
            fxh2 = f(x)

            grad[idx] = (fxh1 - fxh2) / (2*h)
            x[idx] = tmpVal
        return grad

    def sgd(self,f,x0 , lr = 0.01 , iter = 1000 ):
        x = x0
        for i in range(iter):
            grad = self.gradient(f , x)
            x -= lr * grad
        return x

    def sgdHistory(self,f,x0 , lr = 0.01 , iter = 100 ):
        his = []
        his.append(x0)
        x = x0
        for i in range(iter):
            grad = self.gradient(f , x)
            x -= lr * grad
            his.append(list(x))
        return x , his


import math
import numpy as np
import matplotlib.pyplot as plt
import pandas
import scipy.linalg as linalg

# Parameters
np.random.seed(421)
# generating data
class_means = np.array([[0.0, 2.5], [-2.5, -2.0], [2.5, -2.0]])

class_covariances = np.array([[
    [3.2, 0.0],
    [0.0, 1.2]],
    [
        [1.2, 0.8],
        [0.8, 1.2]
    ],
    [
        [1.2, -0.8],
        [-0.8, 1.2]
    ]
])

# number of data points for each class.
class_sizes = np.array([120, 80, 100])

points1 = np.random.multivariate_normal(class_means[0, :], class_covariances[0, :, :], class_sizes[0])
points2 = np.random.multivariate_normal(class_means[1, :], class_covariances[1, :, :], class_sizes[1])
points3 = np.random.multivariate_normal(class_means[2, :], class_covariances[2, :, :], class_sizes[2])
points = np.vstack((points1, points2, points3))

# generating the labels.
y = np.concatenate((np.repeat(1, class_sizes[0]), np.repeat(2, class_sizes[1]), np.repeat(3, class_sizes[2])))

x1 = points[:, 0]
x2 = points[:, 1]
# Plotting Data
plt.figure(figsize=(10, 10))
plt.plot(points1[:, 0], points1[:, 1], "r.", markersize=12)
plt.plot(points2[:, 0], points2[:, 1], "g.", markersize=12)
plt.plot(points3[:, 0], points3[:, 1], "b.", markersize=12)
plt.xlabel("$x_1$")
plt.ylabel("$x_2$")
plt.show()

# Part 3 - Estimation

# number of classes
K = np.max(y)
# number of data points
N = points.shape[0]

# Parameter Estimation
# Mean
# axis = 0
sample_means = [np.mean(points[y == (c + 1)], axis=0) for c in range(K)]
print("sample_means")
print(sample_means)

# Covariances
sample_covariances = [
    np.dot(np.transpose(points[y == (c + 1)] - sample_means[c]), points[y == (c + 1)] - sample_means[c]) / class_sizes[
        c] for c in range(K)]
print("sample_covariances")
print(sample_covariances)

# Class Priors
class_priors = [np.mean(y == (c + 1)) for c in range(K)]
print("Class Priors")
print(class_priors)

# Multivariate Parametric Classification
# From class notes on Multivariate Parametric Classification
D = 3
y_predicted = []
for i in range(points.shape[0]):
    wc0 = [
        -1 / 2 * np.dot(np.dot(np.transpose(sample_means[c]), np.linalg.inv(sample_covariances[c])), sample_means[c]) -
        D / 2 * np.log(2 * math.pi) - 1 / 2 * np.log(np.linalg.det(sample_covariances[c])) + np.log(class_priors[c]) for
        c in range(K)]
    wc = [np.dot(np.linalg.inv(sample_covariances[c]), sample_means[c]) for c in range(K)]
    Wc = [-1 / 2 * np.linalg.inv(sample_covariances[c]) for c in range(K)]
    g = [np.dot(np.dot(np.transpose(points[i]), Wc[c]), points[i]) + np.dot(np.transpose(wc[c]), points[i]) + wc0[c] for
         c in range(K)]
    # take the maximum of gc(x)
    y_predicted.append(np.argmax(g) + 1)
y_predicted = np.array(y_predicted)

# Confusion Matrix
confusion_matrix = pandas.crosstab(y_predicted, y, rownames=['y_pred'], colnames=['y_truth'])
print(confusion_matrix)

# Plotting the decision boundaries
# From lab 03
x1_interval = np.linspace(-6, +6, 1201)
x2_interval = np.linspace(-6, +6, 1201)
x1_grid, x2_grid = np.meshgrid(x1_interval, x2_interval)
# discriminant_values = [Wc[c][0][0] * x1_grid + Wc[c][0][1] * x2_grid + wc[c][0] for c in range(K)]
plt.figure(figsize=(10, 10))
plt.plot(points[y == 1, 0], points[y == 1, 1], "r.", markersize=10)
plt.plot(points[y == 2, 0], points[y == 2, 1], "g.", markersize=10)
plt.plot(points[y == 3, 0], points[y == 3, 1], "b.", markersize=10)
plt.plot(points[y_predicted != y, 0], points[y_predicted != y, 1], "ko", markersize = 12, fillstyle = "none")
# plt.contour(x1_grid, x2_grid, discriminant_values, levels=0, colors="k")
plt.show()


import numpy as np
import pandas as pd

def swap(A, b, i, j):
    A[j, :], A[i, :] = A[i, :], A[j, :].copy()
    b[j], b[i] = b[i], b[j].copy()
    return

def forward(A, b, n):

    for i in range(0, n - 1):
        if A[i][i] == 0:
            pivot = np.nonzero(A[i:, i])[0][0]
            swap(A, b, i, pivot)
        else:
            for j in range(i + 1, n):
                d = A[j][i] / A[i][i]
                for k in range(i + 1, n):
                    A[j, k] = A[j, k] - (d * A[i, k])
                b[j] = b[j] - (d * b[i])
    return

def back(A, b, n):

    if A[n-1, n-1] == 0:
        raise ValueError("System has infinite solutions.")

    for i in range(n-1, -1, -1):
        b[i] = b[i]/A[i, i]
        for j in range(i-1, -1, -1):
            b[j] -= A[j, i]*b[i]

    return

def gaussian_elimination(A, b):
    n = len(b)
    forward(A, b, n)
    back(A, b, n)
    return b

df = pd.read_excel('data.xlsx', engine='openpyxl')
A = df.to_numpy()
b = np.array([3, 7, 11, 16, 21, 26, 24, 28, 23], dtype="float")
print(gaussian_elimination(A, b))


import numpy as np

def kldistance(p, q):
    return np.sum(p * (np.log(p) - np.log(q)))

p = np.array([0.4, 0.6])
q = np.array([0.5, 0.5])
print(kldistance(p, q))
print(kldistance(q, p))


#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
20170425
Resolver sistema de ecuaciones usando algebra lineal

Objetivo: Tomar un sistema de ecuaciones y resolverlo usando algebra de matrices y vectores

Fuentes:
    video de youtube

Status:

Notas:

    Se tiene el sistema de ecuaciones

        1a + 1b = 35
        2a + 4b = 94

    Planteandolo en forma de matrices y vectores:

        AX = B

        Donde A es una matriz, X un vector y B un vector

        A = [1 1, 2 4]
        X = [A B]T
        B = [35 94]T

    Para encontrar X:
        X = A_inversa * B

Keywords:
    robotica, matriz, resolver sistema ecuaciones,

Autor: Jaime Andres Cataño Bernal

"""

import numpy as np

# define matrices
A = np.matrix([[1,1],[2,4]])
B = np.matrix([[35],[94]])

# Find the inverse of A
A_inverse = np.linalg.inv(A)

# Solving for X
X = A_inverse * B

print X


# Suppose the demand for a certain item is given by D(p) -5p^2 7p +600, where p represents the price of the item in dollars.

# a. Find the rate of change of demand with respect to price.
# b. Find and interpret the rate of change of demand when the price is $10.

from sympy import symbols, Limit, Derivative, Integral

p = symbols( 'p' )
fP = -5*p**2 - 7*p + 600

dP = Derivative( fP, p ).doit()

# The rate of change of demand with respect to price is
dP

# When the price is $10, demand is:
dP.subs( { p: 10 } )
# decreasing at a rate of about  107 items for each increase in price of $1.


import numpy as np
from scipy.stats import weibull_min, lognorm
from Bayes import Bayes
from matplotlib import pyplot as plt

testDists = ['norm', 'weibull_min', 'lognorm']

def testNormal(hLen, totN, figSize, pltRange):
    """
    Brief test with data following normal distribution.
    """
    # Create some imaginary data
    obs = np.random.normal(15.4, 1.3, size = totN)
    model = obs + np.random.normal(0.0, 4.5, size = len(obs))

    # Start Testing
    # Create an instance of the object
    bs = Bayes(hLen, distType = 'norm')

    # Use the first #hLen of them for training
    obsTrain = obs[:hLen]
    modelTrain = model[:hLen]

    # The rest to be used dynamically
    obsDyn = obs[hLen:]
    modelDyn = model[hLen:]
    fcst = np.zeros_like(obsDyn)

    # Perform an initial training of the model
    bs.trainMe(obsTrain, modelTrain)

    for ij in range(len(obsDyn)):
        # Provide a correction to the forecast
        fcst[ij] = bs.adjustForecast(modelDyn[ij])

        # Update system
        bs.trainMe([obsDyn[ij]], [modelDyn[ij]])

    # Show evidence!
    plt.figure(figsize = figSize)
    plt.plot(obsDyn[pltRange], label='obs')
    plt.plot(modelDyn[pltRange], '--', label='model')
    plt.plot(fcst[pltRange], '*', label='Bayes')
    plt.title('Normal Dist Data')
    plt.legend()
    plt.show()
    return

def testWeibull(hLen, totN, figSize, pltRange):
    """
    Brief test with data following weibull distribution.
    """
    # Create some imaginary data
    obs = weibull_min.rvs(c = 1.96, scale = 2.1, size = totN) # c: shape
    model = obs + np.random.normal(0.0, 2.5, size = len(obs))

    # Start Testing
    # Create an instance of the object
    bs = Bayes(hLen, distType = 'weibull_min')

    # Use the first #hLen of them for training
    obsTrain = obs[:hLen]
    modelTrain = model[:hLen]

    # The rest to be used dynamically
    obsDyn = obs[hLen:]
    modelDyn = model[hLen:]
    fcst = np.zeros_like(obsDyn)

    # Perform an initial training of the model
    bs.trainMe(obsTrain, modelTrain)

    for ij in range(len(obsDyn)):
        # Provide a correction to the forecast
        fcst[ij] = bs.adjustForecast(modelDyn[ij])

        # Update system
        bs.trainMe([obsDyn[ij]], [modelDyn[ij]])

    # Show evidence!
    plt.figure(figsize = figSize)
    plt.plot(obsDyn[pltRange], label='obs')
    plt.plot(modelDyn[pltRange], '--', label='model')
    plt.plot(fcst[pltRange], '*', label='Bayes')
    plt.title('Weibull Dist Data')
    plt.legend()
    plt.show()
    return

def testLognormal(hLen, totN, figSize, pltRange):
    """
    Brief test with data following lognormal distribution.
    """
    # Create some imaginary data
    obs = lognorm.rvs(s = 0.94, scale = 1.9, size = totN)
    model = obs + np.random.normal(0.0, 2.5, size = len(obs))

    # Start Testing
    # Create an instance of the object
    bs = Bayes(hLen, distType = 'lognorm')

    # Use the first #hLen of them for training
    obsTrain = obs[:hLen]
    modelTrain = model[:hLen]

    # The rest to be used dynamically
    obsDyn = obs[hLen:]
    modelDyn = model[hLen:]
    fcst = np.zeros_like(obsDyn)

    # Perform an initial training of the model
    bs.trainMe(obsTrain, modelTrain)

    for ij in range(len(obsDyn)):
        # Provide a correction to the forecast
        fcst[ij] = bs.adjustForecast(modelDyn[ij])

        # Update system
        bs.trainMe([obsDyn[ij]], [modelDyn[ij]])

    # Show evidence!
    plt.figure(figsize = figSize)
    plt.plot(obsDyn[pltRange], label='obs')
    plt.plot(modelDyn[pltRange], '--', label='model')
    plt.plot(fcst[pltRange], '*', label='Bayes')
    plt.title('Lognormal Dist Data')
    plt.legend()
    plt.show()
    return

if __name__ == '__main__':

    # Define some generic values
    history = 100
    totalNum = 2000
    plotNum = 40

    # Define the plot range and size of the figure
    figSize = (11, 9)
    pIn = int(totalNum * .5)
    pltRange = range(pIn, pIn + plotNum)

    for item in testDists:
        if item.lower() == 'norm':
            print('\n *****   Normal Distribution data testing    ***** ')
            testNormal(history, totalNum, figSize, pltRange)
            print('\n ***** Normal Distribution data testing  END ***** ')
        elif item.lower() == 'weibull_min':
            print('\n *****   Weibull Distribution data testing    ***** ')
            testWeibull(history, totalNum, figSize, pltRange)
            print('\n ***** Weibull Distribution data testing  END ***** ')
        elif item.lower() == 'lognorm':
            print('\n *****   Lognormal Distribution data testing    ***** ')
            testLognormal(history, totalNum, figSize, pltRange)
            print('\n ***** Lognormal Distribution data testing  END ***** ')
        else:
            raise TypeError('Unknown distribution used for testing...')


import numpy as np

# Write a function that takes as input a list of numbers, and returns
# the list of values given by the softmax function.
def softmax(L):
    expL = np.exp(L)
    sumExpL = sum(expL)
    result = []
    for i in expL:
        result.append(i*1.0/sumExpL)
    return result


import numpy

# standard deviation
# dataset
speed = [32, 111, 138, 28, 59, 77, 97]

x = numpy.std(speed)

print("\nMean(average) is:", numpy.mean(speed))
print("\nStandard deviation is:", x)
'''
Standard deviation is most of the values are within
the range of 0.9 from the mean(average) value.
Standard deviation is also equals to square root of
the variance
'''

# variance
'''
variance is the average number of squared differences
between the values and mean(average)
'''
y = numpy.var(speed)
print("\nVariance is:", y)


import os, sys
import numpy as np

def Simpson(func, dp):
    N = len(func)
    integral_sum = 0.0

    if N % 2 == 1:
        k_end = (N-1)//2
    else:
        k_end = N//2 - 1

    for k in range(k_end):
        integral_sum += func[2*k] + 4.0*func[2*k + 1] + func[2*k + 2]

    integral_sum = dp/3.0*integral_sum

    if N % 2 == 0:
        integral_sum += dp/2.0*(func[N - 2]+func[N - 1])

    return integral_sum

def L2norm(x, w):
    if len(x) != len(w):
        print('Mesh x and function don''t match!')
        exit()

    func = np.power(np.abs(w), 2)

    h = x[1] - x[0]                # spacing

    return np.sqrt(Simpson(func, h))

if __name__ == '__main__':
    is_filter = False
    N = 150       # Number of entries for the moving average filter
    funcs = {}
    Idx = 1
    try:
        path = 'C:/Users/mexika/Documents/Qt_code/CudaFEMproject/prak_results/'
        for filename in os.listdir(path):
            if filename.endswith('.txt'):
                with open(path + filename, 'r') as file_read:
                    data = file_read.readlines()
                data = [line.rstrip() for line in data]
                x, y = [], []
                for d in data:
                    x.append(float(d.split()[0]))
                    y.append(float(d.split()[1]))
                if is_filter:
                    y = np.convolve(y, np.ones(N)/N, mode='valid')
                    if N % 2 == 0:
                        x = x[N//2-1:-N//2]
                    else:
                        x = x[(N-1)//2:-(N-1)//2]

                funcs[Idx] = (x,y)
                print(Idx,'\t',filename)
                Idx += 1
    except Exception as e:
        print('Something wrong with postprocessing')
        sys.exit(0)

    for i in range(1, Idx - 1):
        x = funcs[i][0]
        y1 = np.array(funcs[i][1])
        y2 = np.array(funcs[i+1][1])
        norm_y2 = L2norm(x,y2)
        norm_diff = L2norm(x,y1-y2)
        print('L2 norm (y',i,', y',i+1,') =\t', L2norm(x,y1-y2),' ( ', norm_diff/norm_y2*100,'% )\t L2 norm (y',i+1,') =\t',norm_y2, sep='')


"""
Partial Correlation in Python (clone of Matlab's partialcorr)

This uses the linear regression approach to compute the partial
correlation (might be slow for a huge number of variables). The
algorithm is detailed here:

    http://en.wikipedia.org/wiki/Partial_correlation#Using_linear_regression

Taking X and Y two variables of interest and Z the matrix with all the variable minus {X, Y},
the algorithm can be summarized as

    1) perform a normal linear least-squares regression with X as the target and Z as the predictor
    2) calculate the residuals in Step #1
    3) perform a normal linear least-squares regression with Y as the target and Z as the predictor
    4) calculate the residuals in Step #3
    5) calculate the correlation coefficient between the residuals from Steps #2 and #4;

    The result is the partial correlation between X and Y while controlling for the effect of Z

Date: Nov 2014
Author: Fabian Pedregosa-Izquierdo, f@bianp.net
Testing: Valentina Borghesani, valentinaborghesani@gmail.com
"""

import numpy as np
from scipy import stats, linalg

def partial_corr(C):
    """
    Returns the sample linear partial correlation coefficients between pairs of variables in C, controlling
    for the remaining variables in C.

    Parameters
    ----------
    C : array-like, shape (n, p)
        Array with the different variables. Each column of C is taken as a variable

    Returns
    -------
    P : array-like, shape (p, p)
        P[i, j] contains the partial correlation of C[:, i] and C[:, j] controlling
        for the remaining variables in C.
    """

    C = np.asarray(C)
    p = C.shape[1]
    P_corr = np.zeros((p, p), dtype=np.float)
    for i in range(p):
        P_corr[i, i] = 1
        for j in range(i+1, p):
            idx = np.ones(p, dtype=np.bool)
            idx[i] = False
            idx[j] = False
            beta_i = linalg.lstsq(C[:, idx], C[:, j])[0]
            beta_j = linalg.lstsq(C[:, idx], C[:, i])[0]

            res_j = C[:, j] - C[:, idx].dot( beta_i)
            res_i = C[:, i] - C[:, idx].dot(beta_j)

            corr = stats.pearsonr(res_i, res_j)[0]
            P_corr[i, j] = corr
            P_corr[j, i] = corr

    return P_corr


"""
Problem Statement

sum

The sum tool returns the sum of array elements over a given axis.

import numpy

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

print numpy.sum(my_array, axis = 0)         #Output : [4 6]
print numpy.sum(my_array, axis = 1)         #Output : [3 7]
print numpy.sum(my_array, axis = None)      #Output : 10
print numpy.sum(my_array)                   #Output : 10
By default, the axis value is None. Therefore, it performs a sum over all
the dimensions of the input array.

prod

The prod tool returns the product of array elements over a given axis.

import numpy

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

print numpy.prod(my_array, axis = 0)            #Output : [3 8]
print numpy.prod(my_array, axis = 1)            #Output : [ 2 12]
print numpy.prod(my_array, axis = None)         #Output : 24
print numpy.prod(my_array)                      #Output : 24
By default, the axis value is None. Therefore, it performs the product 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 sum tool over axis 0 and then find the product
of that result.

Input Format

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

Output Format

Compute the sum along axis 0. Then, print the product of that sum.

Sample Input

2 2
1 2
3 4
Sample Output

24
Explanation

The sum along axis 0 = [4 6]
The product of this sum = 24
"""
import numpy

n, m = map(int, raw_input().split())
a = numpy.array([map(int, raw_input().split()) for i in range(n)],
                dtype=numpy.int)
sum_array = numpy.sum(a, axis=0)
print numpy.prod(sum_array, axis=0)


import numpy as np

# support functions for perturbation analysis in parabolic partial differential equations
# most code obtained from github repository
# https://github.com/tclaudioe/Scientific-Computing

def cubic_spline(x, y, end=None, k1=0, k2=0, p1=0, p2=0):
    #x: x-coordinates of points
    #y: y-coordinates of points
    #end: Natural, Adjusted, Clamped, Parabolically, NaK

    n = len(x)
    A = np.zeros((3*n-3, 3*n-3))
    b = np.zeros(3*n-3)

    delta_x=np.diff(x)

    #Building the linear system of equations

    #1st property
    for i in np.arange(n-1):
        b[i]= y[i+1]-y[i]
        A[i,3*i:3*(i+1)] = [delta_x[i],delta_x[i]**2,delta_x[i]**3]
    #2nd property
    for i in np.arange(n-2):
        A[(n-1)+i,3*i:3*(i+1)+1]=[1, 2*delta_x[i], 3*delta_x[i]**2, -1]
    #3rd property
    for i in np.arange(n-2):
        A[(n-1)+(n-2)+i,3*i:3*(i+1)+2] = [0, 2, 6*delta_x[i], 0, -2]

    #Ending conditions (4th property)
    if end =='Natural':
        A[-2,1]= 2
        A[-1,-2] = 2
        A[-1,-1] = 6*delta_x[-1]

    elif end == 'Adjusted':
        A[-2,1]= 2
        A[-1,-2] = 2
        A[-1,-1] = 6*delta_x[-1]
        b[-2:] = [k1,k2]

    elif end == 'Clamped':
        A[-2,0]=1
        A[-1,-3:] = [1,2*delta_x[-1],3*delta_x[-1]**2]
        b[-2:] = [p1,p2]

    elif end == 'Parabolically':
        A[-2,2]=1
        A[-1,-1]=1

    elif end == 'NaK':
        A[-2,2:6]=[6,0,0,-6]
        A[-1,-4:]=[6,0,0,-6]

    #Solving the system
    sol = np.linalg.solve(A,b)
    S = {'b':sol[::3],
         'c':sol[1::3],
         'd':sol[2::3],
         'x':x,
         'y':y
        }
    return S

def cubic_spline_eval(xx,S):
    x=S['x']
    y=S['y']
    b=S['b']
    c=S['c']
    d=S['d']
    n=len(x)
    yy=float("nan")
    for i in np.arange(n-1):
        if x[i] <= xx and xx <= x[i+1]:
            yy = y[i]+b[i]*(xx-x[i])+c[i]*(xx-x[i])**2+d[i]*(xx-x[i])**3
    return yy

def cubic_spline_eval2(xx,S):
    x=S['x']
    y=S['y']
    b=S['b']
    c=S['c']
    d=S['d']
    n=len(x)
    yy=np.zeros_like(xx)
    for i in np.arange(n-1):
        jj = np.where(np.logical_and(x[i]<=xx,xx<=x[i+1]))
        yy[jj]=y[i]+b[i]*(xx[jj]-x[i])+c[i]*(xx[jj]-x[i])**2+d[i]*(xx[jj]-x[i])**3
    return yy

def bisect(f, a, b, verb=False, tol=10e-12):
    fa = f(a)
    fb = f(b)
    i = 0
    # Just checking if the sign is not negative => not root  necessarily
    if np.sign(f(a)*f(b)) >= 0:
        print('f(a)f(b)<0 not satisfied!')
        return None

    if verb:
        #Printing the evolution of the computation of the root
        print(' i |     a     |     c     |     b     |     fa    |     fc     |     fb     |   b-a')
        print('----------------------------------------------------------------------------------------')

    while(b-a)/2 > tol:
        c = (a+b)/2.
        fc = f(c)
        if verb:
            print('%2d | %.7f | %.7f | %.7f | %.7f | %.7f | %.7f | %.7f' % (i+1, a, c, b, fa, fc, fb, b-a))
        # Did we find the root?
        if fc == 0:
            print('f(c)==0')
            break
        elif np.sign(fa*fc) < 0:
            b = c
            fb = fc
        else:
            a = c
            fa = fc
        i += 1

    xc = (a+b)/2.
    return xc

def simpsons(myfun, N, a, b, verbose=False, text="", figname=""):
    f = np.vectorize(myfun) # So we can apply it to arrays without trouble
    x = np.linspace(a, b, N+1) # We want N bins, so N+1 points
    if N%2==1:
        if verbose: print("Simpsons rule only applicable to even number of segments")
        return np.nan
    dx = x[1]-x[0]
    xleft   = x[:-2:2]
    xmiddle = x[1::2]
    xright  = x[2::2]
    int_val = sum((f(xleft)+4*f(xmiddle)+f(xright))*dx/3)
    if verbose:
        xbin, ybin = simpsons_bins(f, xleft, xmiddle, xright)
        plot(f, xbin, ybin, int_val, N, text, figname)
    return int_val


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

Copyright (c) 2022 Jongrae.K

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"""

import numpy as np
from numpy import linspace
import numpy.random as rp

import matplotlib.pyplot as plt

# true probability density function (pdf)
var_x = 1;
mean_x = 0;
Omega_x = linspace(-5,5,1000);
px = (1/(np.sqrt(2*np.pi*var_x)))*np.exp(-(Omega_x-mean_x)**2/(2*var_x));

fig, ax = plt.subplots(nrows=1,ncols=1)
ax.plot(Omega_x,px,linewidth=3)

# generate N random numbers with the mean zero and the variance 1 using
# numpy.random.randn
N_all = np.array([100,10000])
x_bin = linspace(-5,5,30)
dx=np.mean(np.diff(x_bin))
line_style = ['rs-','go-']
for N_trial, lnsty in zip(N_all,line_style):
    x_rand = rp.randn(1,N_trial)

    # number of occurance of x_rand in x_bin
    N_occur = np.histogram(x_rand,bins=x_bin)
    N_occur = N_occur[0]

    ax.plot(x_bin[0:-1]+dx/2, N_occur/(dx*N_trial),lnsty);

ax.set_xlabel(r'Random Variable x Sampling Space: $\Omega_x$',fontsize=14)
ax.set_ylabel('probability density function',fontsize=14)
ax.legend((r'True $p(x)$','N=100','N=10,000'),loc='upper right',fontsize=14)

fig.savefig('compare_mu_sgm2_true_estimated_python.pdf')


# https://www.hackerrank.com/challenges/np-polynomials/problem

import numpy

# Inputs
standard_input = """1.1 2 3
0"""

p = [float(s) for s in input().split()]
# 1.1 2 3
x = int(input())
# 0

print(numpy.polyval(p, x))
# 3.0

""" Reference

[poly]

The poly tool returns the coefficients of a polynomial with the given sequence of roots.

print(numpy.poly([-1, 1, 1, 10]))
#Output : [  1 -11   9  11 -10]

[roots]

The roots tool returns the roots of a polynomial with the given coefficients.

print(numpy.roots([1, 0, -1]))
#Output : [-1.  1.]

[polyint]

The polyint tool returns an antiderivative (indefinite integral) of a polynomial.

print(numpy.polyint([1, 1, 1]))
#Output : [ 0.33333333  0.5         1.          0.        ]

[polyder]

The polyder tool returns the derivative of the specified order of a polynomial.

print(numpy.polyder([1, 1, 1, 1]))
#Output : [3 2 1]

[polyval]

The polyval tool evaluates the polynomial at specific value.

print(numpy.polyval([1, -2, 0, 2], 4))
Output : 34

[polyfit]

The polyfit tool fits a polynomial of a specified order to a set of data using a least-squares approach.

print(numpy.polyfit([0,1,-1, 2, -2], [0,1,1, 4, 4], 2)
#Output : [  1.00000000e+00   0.00000000e+00  -3.97205465e-16]

-----------
The functions polyadd, polysub, polymul, and polydiv also handle proper addition, subtraction, multiplication, and division of polynomial coefficients, respectively.

"""

__Training__/Python - HackerRank/16. Numpy/Polynomials.py


from IMLearn.learners import UnivariateGaussian, MultivariateGaussian
import numpy as np
import plotly.graph_objects as go
import plotly.io as pio
import math

pio.templates.default = "simple_white"

def test_univariate_gaussian():
    # Question 1 - Draw samples and print fitted model
    mu, var, m = 10, 1, 1000

    data = np.random.normal(mu, var, m)
    estimator = UnivariateGaussian().fit(data)
    print(f"({estimator.mu_}, {estimator.var_})")

    # Question 2 - Empirically showing sample mean is consistent
    x = np.arange(10, 1010, 10)  # x = [10, 20,..., 100, 110, ..., 1000]
    y = []
    for i in x:
        estimator.fit(data[:i])
        y.append(math.fabs(mu - estimator.mu_))

    go.Figure(go.Scatter(x=x, y=y, mode='markers+lines'),
              layout=go.Layout(title="absolute distance between the estimated and true value of the "
                                     r"expectation, as a function of the sample size",
                               xaxis_title="number of samples",
                               yaxis_title="r$|\mu - \hat\mu|$")).show()

    # Question 3 - Plotting Empirical PDF of fitted model
    estimator.fit(data)
    pdf_data = estimator.pdf(data)

    go.Figure(go.Scatter(x=data, y=pdf_data, mode='markers'),
              layout=go.Layout(title="Empirical PDF of fitted model",
                               xaxis_title="samples",
                               yaxis_title="PDF values")).show()

def test_multivariate_gaussian():
    # Question 4 - Draw samples and print fitted model
    m = 1000
    mu = np.array([0, 0, 4, 0])
    cov = np.array([[1, 0.2, 0, 0.5],
                    [0.2, 2, 0, 0],
                    [0, 0, 1, 0],
                    [0.5, 0, 0, 1]])

    data = np.random.multivariate_normal(mu, cov, m)
    mult_estimator = MultivariateGaussian().fit(data)

    print(mult_estimator.mu_)
    print(mult_estimator.cov_)

    # Question 5 - Likelihood evaluation
    f = np.linspace(-10, 10, 200)
    log_likelihood_data = np.empty([f.size, f.size])

    for i in range(f.size):
        for j in range(f.size):
            mu = np.array([f[i], 0, f[j], 0])
            log_likelihood_data[i][j] = mult_estimator.log_likelihood(mu, cov, data)

    go.Figure(go.Heatmap(x=f, y=f, z=log_likelihood_data),
              layout=go.Layout(
                  title="Log Likelihood Heatmap",
                  xaxis_title="$f3\\ values$",
                  yaxis_title="$f1\\ values$")).show()

    # Question 6 - Maximum likelihood
    f1_index, f3_index = np.where(log_likelihood_data == np.amax(log_likelihood_data))
    f1, f3 = f[f1_index].round(3),  f[f3_index].round(3)
    # The Exercise 1 description didn't ask to print... to print uncomment next line
    # print(f1, f3)

if __name__ == '__main__':
    np.random.seed(0)
    test_univariate_gaussian()
    test_multivariate_gaussian()


import numpy as np

# An array has a shape given by the number of elements along each axis
a = np.floor(10*np.random.random((3,4)))
print("Array a : ",a)
print("Shape : ",a.shape)

# The shape of an array can be changed with various commands. Note that the following three
# commands all return a modified array, but do not change the original array

# returns the array, flattened
print("ravel : ",a.ravel())
# returns the array with a modified shape
print("reshape : ",a.reshape(6,2))
# returns the array, transposed
print("transposed : ",a.T)
print("transposed shape : ",a.T.shape)
print("array shape : ",a.shape)

# The reshape function returns its argument with a modified shape, whereas the ndarray.resize
# method modifies the array itself
print("resize : ",a.resize((2,6)))

# If a dimension is given as -1 in a reshaping operation, the other dimensions are automatically calculated
print("-1 in reshaping operation : ",a.reshape(3,-1))


# Reimplementing the notebook: https://github.com/pranavkantgaur/CourseraDLSpecialization/blob/master/Course1/Week1/Python_Basics_With_Numpy_v3a.ipynb from scratch.

import math
import numpy as np
import time

def basic_sigmoid(x):
    s = 1 / (1 + math.exp(-1.0 * x))
    return s

# limitation of math packahge
print(basic_sigmoid(3))
x = np.array([1, 2, 3])
print(np.exp(x))
#print(math.exp(x))

# without broadcasting
a = np.array([1, 2, 3])
b = np.array([2, 2, 2])
print ("a * b is: ", a * b)

#broadcasting
x = x + 3 # more memory-efficient
print("x is: ", x)

# two dimensions are same if, they are equal or one of them is 1

# axes are compared starting from the trailing axis to upwards.

# dimensions with 1 are streched or 'copied' to match the other.

# broadcasting in practice
x = np.arange(4)
print("x shape: ", x.shape)

xx = x.reshape(4, 1)
y = np.ones(5)
z = np.ones((3,4))

#print ("x + y is: ", x + y)
print ("xx + y is: ", xx + y)

# outer-addition operation using broadcasting
a = np.array([0, 1, 2, 3])
b = np.array([1, 2, 3])
print("Curent a's shape is: ", a.shape)
a = a[:, np.newaxis]
print("New a shape is: ", a.shape)

# implement sigmoid using numpy:
def numpy_sigmoid(x):
    s = 1 / (1 + np.exp(-1.0 * x))
    return s

x = np.array([1, 2, 3, 4])
print("Numpy's version of sigmoid:", numpy_sigmoid(x))

# sigmoid gradient, required for backpropogation implementation
# sigmoid graidient: sigma * (1- sigma)

def sigmoid_gradient(x):
    y = numpy_sigmoid(x)
    g = numpy_sigmoid(x) * (1 - numpy_sigmoid(x))
    return g

print("Sigmoid graidnent is: ", sigmoid_gradient(x))

# Reshaping arrays, exploring np.shape and np.reshape functions
# Note: np.reshape() and np.ndarray.reshape() are equivalent solutions to reshaping objects.
# np.reshape() is a function, whereas np.ndarray.reshape() is a method of class ndarray

x = np.zeros([256, 256, 3])
print("Current shape of x image is: ", x.shape)
x = x.reshape([256* 256 * 3, 1])
print("Image x shape is: ", x.shape)
y = x + 3 # result will be (256 X 256 X 3, 1)
print ("Shape of the augmented image is: ", y)

# implementing img2vect function for converting an 3-channel image to a 1D array
def img2vect(image):
  v = image.reshape(image.shape[0] * image.shape[1] * image.shape[2], 1)
  return v

image = np.array([[[1, 2, 3], [4, 5, 6], [7, 8, 9]], [[10,11,12],[13, 14, 15],[16, 17, 18]], [[19, 20, 21],[22, 23, 24],[25, 26, 27]]]) # 3 x3 x 3 array
v = img2vect(image)
print ("image vector: ", v)
print ("shape of image vector: ", v.shape)

# normalizing rows
def normalizeRows(x):
    x = np.linalg.norm(x, axis = 1, keepdims=True)
    return x

x = np.array([[1, 2, 3], [4, 5, 6]])
print("Original vector: ", x)
x_normalization_vector = normalizeRows(x)
normalized_x = x / x_normalization_vector # broadcasting, x.shape = (2, 3), x_normalization_vector.shape = (2, 1)
# x_normalization_vector reshaped into 2,3
print("Normalized vector: ", normalized_x)

# broadcasting and softmax function
def softmax(x):
    exp_x = np.exp(x)
    exp_x_normalization_vector = np.sum(exp_x, axis = 1, keepdims = True) #  keepdims=True makes sure that the following broadcasting will work.
    return exp_x / exp_x_normalization_vector

x = np.array([[1, 2, 3]]) # in nn forward inference, x will have shape (1, m), m: # training examples

x = np.array([
        [9, 2, 5, 0, 0],
            [7, 5, 0, 0 ,0]])

print("Softmax output: ", softmax(x))

# Vectorization: Classical dot, outer and elementwise product implementations
def classic_dot_product(v1, v2):
    vector_length = len(v1)
    dot_product = 0.0
    tick = time.process_time()
    for i in range(vector_length):
        dot_product += v1[i] * v2[i]
    tock = time.process_time()
    print("classic dot product took: ", tock - tick, "milliseconds!!")
    return dot_product

v1 = [1, 2, 4, 5, 6]
v2 = [7, 8, 9, 10, 11]
print("dot product of v1, v2: ", classic_dot_product(v1, v2))

def classic_outer_product(v1, v2):
    outer = np.zeros((len(v1), len(v2)))
    tick = time.process_time()
    for i in range(len(v1)):
        for j in range(len(v2)):
            outer[i, j] = v1[i] * v2[j]
    tock = time.process_time()
    print("classic outer product took: ", tock - tick, "milliseconds!!")
    return outer

print("outer product of v1, v2: ", classic_outer_product(v1, v2))

def classic_elementwise_product(v1, v2):
    elementwise_product = np.zeros((len(v1), 1))
    tick = time.process_time()
    for i in range(len(v1)):
        elementwise_product[i] = v1[i] * v2[i]
    tock = time.process_time()
    print("classic elementwise product took: ", tock-tick , "millisecods!!")
    return elementwise_product

print("classic elementwise product: ", classic_elementwise_product(v1, v2))

def classic_general_dot_product(v1):
    W = np.random.rand(3, len(v1))
    tick = time.process_time()
    gdot = np.zeros((W.shape[0], 1))
    for i in range(W.shape[0]):
        for j in range(len(v1)):
            gdot[i] += W[i, j] * v1[j]
    tock = time.process_time()
    print("classical general dot product took: ", tock - tick, "ms!!")
    return gdot

print("classic general dot product: ", classic_general_dot_product(v1))

## Lets Vectorize this code!!
def vectorized_dot_product(v1, v2):
  tick = time.process_time()
  dot_product = np.dot(v1, v2)
  tock = time.process_time()
  print("vectorized dot product took: ", tock - tick, "ms!!")
  return dot_product

print("vectorized dot product: ", vectorized_dot_product(v1, v2))

def vectorized_outer_product(v1, v2):
   tick = time.process_time()
   outer_product = np.outer(v1, v2)
   tock = time.process_time()
   print("vectorized outer product took: ", tock - tick, "ms!!")
   return outer_product

print("vectorized dot product: ", vectorized_outer_product(v1, v2))

def vectorized_elementwise_product(v1, v2):
    tick = time.process_time()
    elementwise_prod = np.multiply(v1, v2)
    tock = time.process_time()
    print("vectorized elementwise product took: ", tock - tick, "ms!!")
    return elementwise_prod

print("vectorized elementwise product: ", vectorized_elementwise_product(v1, v2))

def vectorized_general_dot_product(v1):
    W = np.random.rand(3, len(v1))
    tick = time.process_time()
    general_dot_product = np.dot(W, v1)
    tock = time.process_time()
    print("vectorized general dot product took: ", tock - tick, "ms!!")
    return general_dot_product

print("vectorized general dot product: ", vectorized_general_dot_product(v1))

# implementing numpy version of loss functions L1 and L2
def vectorized_L1(yhat, y):
    loss = np.sum(np.abs(yhat - y)) # yhat and y are (m, 1) vectors
    return loss

yhat = np.array([0.9, 0.2, 0.1, 0.4, 0.9])
y = np.array([1, 0, 0, 1, 1])
print("vectorized L1 result: ", vectorized_L1(yhat, y))

def vectorized_L2(yhat, y):
    loss = np.sum(np.square(yhat - y))
    return loss

print("vectorized L2 result: ", vectorized_L2(yhat, y))


'''
# Linear Regression: Decomposition Method
#----------------------------------
#
# Given Ax=b, solving for A:  y=a1*x1+a2*x2, a1=1
  for the sample  number of m
  XA=Y     shapel X:[m 2]  A:[2 1] Y:[m 1]
# This function shows how to use Tensorflow to
# solve linear regression via the matrix inverse.
why:comuter the INVERSE  (X.T*X)^(-1)  is inefficient when m ,n is big
# Given Ax=b, and a Cholesky decomposition such that
#  X.T*X= L*L' then we can get solve for A via
 X*A=Y->X.T*X*A=X.T*Y  s.t:X.T*X=L*L' ->L*L'*A=X.T*Y
 s.t:L'*A=Z  -> L*Z=X.T*Y
# 1) L*Z=X.T*Y  -> Z
# 2) L'*A=Z     -> A
'''
import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf
from tensorflow.python.framework import ops
ops.reset_default_graph()
sess=tf.Session()
x_vals=np.linspace(0,10,100)
y_vals=x_vals+np.random.normal(0,1,100)
x_vals_column=np.transpose(np.matrix(x_vals))
ones_column=np.matrix(np.ones((100,1)))#ones_column = np.transpose(np.matrix(np.repeat(1, 100)))
x=np.column_stack((ones_column,x_vals_column))
y=np.matrix(y_vals).T#y=np.transpose(np.matrix(y_vals))

#create tensors
x_tensor=tf.constant(x)
y_tensor=tf.constant(y)
# Find Cholesky Decomposition
x_xt=tf.matmul(tf.transpose(x_tensor),x_tensor)
L=tf.cholesky(x_xt)
#solve L*Z=X.T*Y
xt_y=tf.matmul(tf.transpose(x_tensor),y_tensor)
Z=tf.matrix_solve(L,xt_y)
#solve L'*A=Z
A=tf.matrix_solve(tf.transpose(L),Z)
A_eval=sess.run(A)
print("A:\n",A_eval)

#get the best fit line
best_fit_y=[]
for i in x_vals:
    best_fit_y.append(A_eval[0]+i*A_eval[1])
#best_fit_y=(np.dot(x,np.matrix(A_eval))).tolist()

#plot the fit line
plt.plot(x_vals,y_vals,"o",label="Data")
plt.plot(x_vals,best_fit_y,'r-',label="Best fit line",linewidth=3)
plt.legend(loc='upper letf')
plt.show()

cookbook/3 Linear Regression/Decomposition Method.py


import sympy

cos = sympy.cos
sin = sympy.sin
atan = sympy.atan2
acos = sympy.acos
asin = sympy.asin
pi = sympy.pi
sqrt = sympy.sqrt

tht = sympy.symbols('theta', real=True)
# xhat = 2*cos(tht)**2-sin(tht)**2
# yhat = 3*cos(tht)*sin(tht)
xhat = (2*cos(tht)**2-sin(tht)**2).expand().simplify()
yhat = (3*cos(tht)*sin(tht)).expand().simplify()
rsqr = xhat**2+yhat**2
# rsqr = xhat.expand().simplify()**2+yhat.expand().simplify()**2

sympy.pprint(xhat)
sympy.pprint(yhat)
# sympy.pprint(rsqr)
tidy_r2 = rsqr.expand().simplify()
sympy.pprint(tidy_r2)

# sympy.pprint(sqrt(rsqr))
sympy.pprint(sqrt(tidy_r2).expand().simplify())
tidy_r1 = sqrt(tidy_r2)

phi_tan = atan(yhat,xhat)
phi_sin = asin(yhat/tidy_r1)
phi_cos = acos(xhat/tidy_r1)

term1 = cos(phi_cos)
term2 = 3*cos(phi_cos-2*tht)
term2_alt = 3*(cos(phi_cos)*cos(2*tht)+sin(phi_sin)*sin(2*tht))

print('term1')
sympy.pprint(term1)
sympy.pprint(term2)
sympy.pprint(term2.expand())
sympy.pprint(term2_alt)
print('term2')
sympy.pprint(term2_alt.expand().simplify())


# -*- coding: utf-8 -*-
"""
Created on Mon Mar 29 19:56:28 2021

@author: Connor
"""
import numpy as np

def ode45_step(f, x, t, dt, *args):
    """
    One step of 4th Order Runge-Kutta method
    """
    k1 = dt * f(t, x, *args)
    k2 = dt * f(t + 0.5*dt, x + 0.5*k1, *args)
    k3 = dt * f(t + 0.5*dt, x + 0.5*k2, *args)
    k4 = dt * f(t + dt, x + k3, *args)
    return x + 1/6. * (k1 + 2*k2 + 2*k3 + k4)

def ode45(f, t, x0, *args):
    """
    4th Order Runge-Kutta method
    """
    n = len(t)
    x = np.zeros((n, len(x0)))
    x[0] = x0
    for i in range(n-1):
        dt = t[i+1] - t[i]
        x[i+1] = ode45_step(f, x[i], t[i], dt, *args)
    return x


#Autor: Angel Octavio Parada Flores
import matplotlib.pyplot as plt
import numpy as np
import sympy as sp
import math as mt

def Fourier(B_0, A_m, B_m, m, k, y):
    VA = 0
    VB = 0
    for i in range(0, m):
        VA += A_m[i]*np.sin((i+1)*2*k*y)
        VB += B_m[i]*np.cos((i+1)*2*k*y)
    return B_0 + VA + VB

x = sp.symbols("x")
m = int(input('Número de armónicos:', ))
I = float(input('Extremo inicial del periodo:',))
T = float(input('Periodo:', ))
F = sp.sympify(input('Función:', ))
p1 = input('¿Se va a reflejar la función? [S/n]:',)
p2 = 0
if p1 == 'n':
    p2 = input('¿Es una función en dos partes? [S/n]:',)

G = 0
if p1 == 'S':
    G = -F.subs(x, x - T/2)
elif p1 == 'n' and p2 == 'n':
    G = F
elif p1 == 'n' and p2 == 'S':
    G = sp.sympify(input('Función 2:', ))

k = mt.pi/T
B_0 = sp.integrate(F/T, (x, I, I+T/2)) + sp.integrate(G/T, (x, I+T/2, I+T))
A_m = []
B_m = []
for i in range (1, m+1):
    A_m.append(sp.integrate(F*(2/T)*sp.sin(i*2*k*x), (x, I, I+T/2)) + sp.integrate(G*(2/T)*sp.sin(i*2*k*x), (x, I+T/2, I+T)))
    B_m.append(sp.integrate(F*(2/T)*sp.cos(i*2*k*x), (x, I, I+T/2)) + sp.integrate(G*(2/T)*sp.cos(i*2*k*x), (x, I+T/2, I+T)))

y = np.arange(-T*3, T*3, 0.01)
plt.figure(figsize=(7,7))
plt.plot(y, Fourier(B_0, A_m, B_m, m, k, y), label = 'Núm. armónicos=' + repr(m))
plt.legend()
plt.grid()
plt.show()


import numpy as np

EPS = 1e-12

def safe_div(numerator, denominator):
    return numerator / (denominator + EPS)

def entropy(p, normalized=True):
    p = np.array(p, dtype=np.float32)
    if not normalized:
        p /= np.sum(p)
    ent = -1. * np.sum(p * np.log(p))
    return ent


'''
本模块储存着部分常用的模型

This module stores some commonly used models
'''
import numpy as np
from maysics import constant
from scipy.integrate import solve_ivp
from scipy.sparse import csr_matrix

def linear_r(x, y):
    '''
    线性回归模型

    参数
    ----
    x：一维或二维ndarray，自变量
    y：一维或二维ndarray，因变量

    返回
    ----
    一维ndarray：系数行矩阵
    损失函数：平均平方误差mse

    Linear Regression Model

    Parameters
    ----------
    x: 1-D or 2-D ndarray, independent variable
    y: 1-D or 2-D ndarray, dependent variable

    Return
    ------
    1-D ndarray: coefficient row matrix
    loss: mean squared error: mse
    '''
    x = np.array(x)
    if len(x.shape) == 1:
        x = np.array([x]).T
    y = np.array(y)
    x = np.hstack((x, np.ones((x.shape[0], 1))))
    coef = np.linalg.lstsq(x, y, rcond=None)[0].reshape(-1)
    y_pre = np.dot(x, np.array([coef]).T).reshape(y.shape)
    mse = ((y_pre - y)**2).mean()
    return coef, mse

def logistic(t, N0, r, K):
    '''
    Logistic人口增长模型
    该模型可得到解析解
    解的形式为：Nt = K * N0 / (N0 + (K - N0) * e**(-r * t))
    其中，Nt为t时刻的人口数

    参数
    ----
    t：时间
    N0：数或数组，现有人口数
    r：数类型，人口自然增长率
    K：数类型，环境资源允许的稳定人口数

    返回
    ----
    数，Nt

    Logisyic population growth models
    solution: Nt = K * N0 / (N0 + (K - N0) * e**(-r * t))
    Nt is the population at time 't'

    Parameters
    ----------
    t: time
    N0: num or array, initial population
    r: num, natural population growth rate
    K: num, stable population allowed by environmental resources

    Return
    ------
    num, Nt
    '''
    Nt_pre_down_ = N0 + (K - N0) * np.e**(-r * t)
    Nt = K * N0 / Nt_pre_down_
    return Nt

class ED():
    '''
    传染病模型
    本类可构建SI模型、SIR模型、SIRS模型、SEIR模型
    S是易感染者
    E是暴露者，染病但还不具有传染能力
    I是感染者，带有传染能力
    R是康复者(带有免疫力)或死者

    参数
    ----
    I0：数类型，初始感染者
    K：数类型，样本总数
    beta：数类型，感染率
    R：数类型，可选，初始康复者(带有免疫力)或死者，默认为0
    E：数类型，可选，暴露者，默认为0

    mathematical models of epidemic diseases
    this class is used to buil SI, SIR, SIRS, SEIR
    S means susceptible people
    E means exposed people, which are infected without ability to infect
    I means infected people with ability to infect
    R means recovered people with immunity or dead people

    Parameters
    ----------
    I0: initial infected people
    K: sample size
    beta: infection rate
    R: num, callable, recovered people with immunity or dead people, default=0
    E: num, callable, exposed people, default=0
    '''
    def __init__(self, I0, K, beta, R=0, E=0):
        self.I0 = I0
        self.K = K
        self.beta = beta
        self.R = R
        self.E = E
        self.S = K - I0 - R - E

    def SI(self, t):
        '''
        SI模型：
        该模型不需要再额外输入参数，且可得到解析解
        解的形式为：I = K*(1-(K-I0)/(K+I0+I0*e**(beta*K*t)))

        参数
        ----
        t：数或一维数组，需要预测的时间

        返回
        ----
        元组，(S(t), I(t))

        SI:
        no more parameters
        solution: I = K*(1-(K-I0)/(K+I0+I0*np.e**(beta*K*t)))

        Parameter
        ---------
        t: num or 1-D array, time for prediction

        Return
        ------
        tuple, (S(t), I(t))
        '''
        I_pre_down_ = self.K + self.I0 * (np.e**(self.beta * self.K * t) - 1)
        I_pre_up_ = self.K - self.I0
        I_func_ = self.K * (1 - I_pre_up_ / I_pre_down_)
        S_func_ = self.K - I_func_
        return S_func_, I_func_

    def SIR(self, gamma, t_span, method='RK45', t_eval=None):
        '''
        SIR模型：
        该模型不能得到解析解，给出的是基于solve_ivp得到的数值解数组

        参数
        ----
        gamma：数类型，康复率
        t_span：元组形式，求解的上下限
        method：字符串形式，可选，求解方法，可选择'RK45'、'RK23'、'DOP835'、'Radau'、'BDF'、'LSODA'
        t_eval：数组形式，可选，每当t等于该数组中的值时，会生成一个数值解

        返回
        ----
        solve_ivp数值解，顺序是S, I, R

        SIR:

        Parameters
        ----------
        gamma: num, recovery rate
        t_span: tuple, limits of solution
        method: str, callable, solving method, 'RK45', 'RK23', 'DOP835', 'Radau', 'BDF', 'LSODA' are optional
        t_eval: list, callable, when 't' equals the value in the list, it will generate a numerical solution

        Return
        ------
        numerical solution of solve_ivp, the order is S, I, R
        '''
        y0 = [self.S, self.I0, self.R]
        def epis_equas(t, x):
            y1 = -self.beta * x[1] * x[0]
            y2 = self.beta * x[1] * x[0] - gamma * x[1]
            y3 = gamma * x[1]
            return y1, y2, y3
        result = solve_ivp(epis_equas, t_span=t_span, y0=y0, method=method, t_eval=t_eval)
        return result.y

    def SIRS(self, gamma, alpha, t_span, method='RK45', t_eval=None):
        '''
        SIRS模型：
        该模型不能得到解析解，给出的是基于solve_ivp得到的数值解数组

        参数
        ----
        gamma：数类型，康复率
        alpha：衡量康复者获得免疫的时间
        t_span：元组形式，求解的上下限
        method：字符串形式，可选，求解方法，可选择'RK45'、'RK23'、'DOP835'、'Radau'、'BDF'、'LSODA'
        t_eval：数组形式，可选，每当t等于该数组中的值时，会生成一个数值解

        返回
        ----
        solve_ivp数值解，顺序是S, I, R

        SIRS:

        Parameters
        ----------
        gamma: num, recovery rate
        alpha: measuring the time that the recovered people with immunity
        t_span: tuple, limits of solution
        method: str, callable, solving method, 'RK45', 'RK23', 'DOP835', 'Radau', 'BDF', 'LSODA' are optional
        t_eval: list, callable, when 't' equals the value in the list, it will generate a numerical solution

        Return
        ------
        numerical solution of solve_ivp, the order is S, I, R
        '''
        y0= [self.S, self.I0, self.R]
        def epis_equas(t, x):
            y1 = -self.beta * x[1] * x[0] + alpha * x[2]
            y2 = self.beta * x[1] * x[0] - gamma * x[1]
            y3 = gamma * x[1] - alpha * x[2]
            return y1, y2, y3
        result = solve_ivp(epis_equas, t_span=t_span, y0=y0, method=method, t_eval=t_eval)
        return result.y

    def SEIR(self, gamma1, gamma2, alpha, t_span, method='RK45', t_eval=None):
        '''
        SEIR模型：
        该模型不能得到解析解，给出的是基于solve_ivp得到的数值解数组

        参数
        ----
        gamma1：数类型，潜伏期康复率
        gamma2：数类型，患者康复率
        alpha：数类型，衡量康复者获得免疫的时间
        t_span：元组形式，求解的上下限
        method：字符串形式，可选，求解方法，可选择'RK45'、'RK23'、'DOP835'、'Radau'、'BDF'、'LSODA'
        t_eval：数组形式，可选，每当t等于该数组中的值时，会生成一个数值解

        返回
        ----
        solve_ivp数值解，顺序是S, E, I, R

        SEIR:

        Parameters
        ----------
        gamma1: num, recovery rate of incubation
        gamma2: num, recovery rate of patients
        alpha: num, measuring the time that the recovered people with immunity
        t_span: tuple, limits of solution
        method: str, callable, solving method, 'RK45', 'RK23', 'DOP835', 'Radau', 'BDF', 'LSODA' are optional
        t_eval: list, callable, when 't' equals the value in the list, it will generate a numerical solution

        Return
        ------
        numerical solution of solve_ivp, the order is S, E, I, R
        '''
        y0 = [self.S, self.E, self.I0, self.R]
        def epis_equas(t, x):
            y1 = -self.beta * x[2] * x[0]
            y2 = self.beta * x[2] * x[0] - (alpha + gamma1) * x[1]
            y3 = alpha * x[1] - gamma2 * x[2]
            y4 = gamma1 * x[1] + gamma2 * x[2]
            return y1, y2, y3, y4
        result = solve_ivp(epis_equas, t_span=t_span, y0=y0, method=method, t_eval=t_eval)
        return result.y

class Leslie():
    '''
    Leslie模型
    解的形式为：Nt = M**t * N0
    其中，Nt是t时刻的个体数列表，M是Leslie矩阵

    参数
    ----
    N0：一维数组，各年龄层初始个体数目
    r：一维数组，各年龄层的生殖率
    s：一维数组，各年龄层到下一个年龄层的存活率
    age_range：整型，年龄段的跨度，默认为1

    属性
    ----
    Leslie_matrix：莱斯利矩阵

    Leslie model
    solution: Nt = M**t * N0
    Nt is the list of individuals at time 't' , M is Leslie matrix

    Parameters
    ----------
    N0: 1-D array, initial number of individuals in each age group
    r: 1-D array, reproductive rate of each age group
    s: 1-D array, survival rate to next age group of each group
    age_range: int, the span of age groups, default=1

    Attribute
    ---------
    Leslie_matrix: Leslie matrix
    '''
    def __init__(self, N0, r, s, age_range=1):
        self.N0 = np.array(N0)
        self.r = np.array(r)
        self.s = np.array(s)
        self.age_range = age_range

        Leslie_matrix = np.zeros((len(s), len(N0)))
        Leslie_matrix = np.vstack((r, Leslie_matrix))
        for i in range(1, len(N0)):
            Leslie_matrix[i][i-1] = s[i-1]
        self.Leslie_matrix = csr_matrix(Leslie_matrix)

    def predict(self, t):
        '''
        参数
        ----
        t：数或一维数组，时间

        返回
        ----
        数，Nt

        Parameter
        ---------
        t: num or 1-D array, time

        Return
        ------
        num, Nt
        '''
        t_times = t // self.age_range
        dense_Leslie_matrix = self.Leslie_matrix.todense()
        Nt = self.N0 * dense_Leslie_matrix**t_times
        return np.array(Nt)[0]


#Brunston Poon (c) 2015, MIT License
import numpy as np
from scipy import stats
import matplotlib.pyplot as plt
np.set_printoptions(suppress=True)

#data = np.loadtxt("gravity.csv",delimiter=",")
data = np.loadtxt("gravity.txt")
p, t = data[:,0], data[:,1]
#print("p:", p)
#print("t:", t)
v = []
for position in range(len(p)):
    if position == 0:
        v.append(p[position]/0.025)
    if position > 0:
        v.append((p[position]-p[position-1])/0.025)
plt.plot(t,p, 'o', label="Position vs Time", markersize = 3)
plt.legend()
plt.show()
plt.plot(t,v,'o', label="Velocity (from avg velocity) vs Time", markersize = 3)
plt.legend()
plt.show()

poly = np.polyfit(t,p,2)
print("p(t), ax^2+bx+c = {0}x^2 + {1}x + {2}".format(poly[0], poly[1], poly[2]))
A = np.vstack([t, np.ones(len(t))]).T
vtm, vtc = np.linalg.lstsq(A, v)[0]

vderiv = []
for position in range(len(p)):
    vderiv.append(2*poly[0]*position + poly[1])
plt.plot(t,vderiv,'o', label="Velocity (from deriv) vs Time", markersize = 3)
plt.legend()
plt.show()
print("v(t) from v_avg, cm/s = {0}x + {1}".format(vtm, vtc))
print("a(t) from v_avg, cm/m^s = {0}".format(vtm))
print("a(t) from v_avg, m/m^s = {0}".format(vtm/100))
print("a(t) from p(T), m/m^s = 2*a/100 = {0}".format(2*poly[0]/100))


# -*- coding: utf-8 -*-
"""
Created on Wed Dec  5 20:13:48 2018

@author: Moaz Magdy
"""
import numpy as np
import matplotlib.pyplot as plt

#Simple Linear regression without using matrices

# y = mx + b
# m = theta1, b = theta0

def cal_error(m,b,points): #Difference between labels and predictions
        totalerr = np.zeros(len(points))
        for i in range(len(points)):
            x = points[i,0]
            y = points[i,1]
            totalerr[i] = (y - ((m*x) + b))**2
        return sum(totalerr)/(float(len(points)))

def gradient_descent(learning_rate,num_iterations,initial_m,initial_b,points):
        N = len(points)
        plt.scatter(points[:,0], points[:,1])
        plt.show()
        updated_b = initial_b
        updated_m = initial_m
        for j in range(num_iterations):
            temp_b = 0
            temp_m = 0
            for i in range(0, len(points)):
                x = points[i,0]
                y = points[i,1]
                temp_b += -(2/N) * (y - ((initial_m * x) + initial_b))        # += To sum all values sequentially
                temp_m += -(2/N) * (y - ((initial_m * x) + initial_b)) * x
            updated_b = initial_b - (learning_rate * temp_b)
            updated_m = initial_m - (learning_rate * temp_m)
            initial_m = updated_m
            initial_b = updated_b
        return [updated_b, updated_m]

def run():
     points = np.loadtxt('C:\ex1data1.txt',delimiter=',')
     learning_rate = 0.0001
     num_iterations = 1000
     initial_m = 0
     initial_b = 0
     [b, m] = gradient_descent(learning_rate,num_iterations,initial_m,initial_b,points)
     print ("After {0} iterations b = {1}, m = {2}, error = {3}".format(num_iterations,b,m,cal_error(m,b,points)))

if __name__ == "__main__":
    run()


"""
@package coord
@author Anna Schneider
@version 0.1
@brief Contains class for Coord
"""

# import from standard library
import math

# import external packages
import numpy as np

class Coord(object):
    """ Cartesian and polar coordinates for given (x,y) pair.
        theta is in range (-pi, pi), degrees is in range(-180,180)
    """
    ##
    # @var x
    # @brief Float for x coord (Cartesian)
    #
    # @var y
    # @brief Float for y coord (Cartesian)

    def __init__(self, dx, dy):
        """ Constructor. Calculates (r, theta) given (x,y).

        @param dx Float for x coord

        @param dy Float for y coord

        """
        self.x = float(dx)
        self.y = float(dy)
        self._theta = None
        self._degrees = None
        self._r = None

    @property
    def r(self):
        """ Distance from the origin """
        if self._r is None:
            self._r = math.sqrt(self.x*self.x + self.y*self.y)
        return self._r

    @property
    def theta(self):
        """ Angle in radians for (r,theta) """
        if self._theta is None:
            if self.r > 0:
                c = self.x / self.r
                s = self.y / self.r
                self._theta = math.atan2(s,c)
            else:
                self._theta = 0.0

        # return
        return self._theta

    @property
    def degrees(self):
        """ Angle in degrees for (r,theta) """
        if self._degrees is None:
            self._degrees = math.degrees(self.theta)
        return self._degrees

    def rotate(self, radians):
        """ Return a new Coord that is rotated counterclockwise
            by the given number of radians. """
        new_x = self.x * math.cos(radians) + self.y * -math.sin(radians)
        new_y = self.x * math.sin(radians) + self.y * math.cos(radians)
        return Coord(new_x, new_y)

    def __repr__(self):
        """ Returns a printable string. """
        retstr = "(x,y) = (%2.1f, %2.1f); " % (self.x,self.y)
        degs = np.remainder(self.degrees, 360.0)
        retstr += "(r,theta) = (%2.1f, %3.1f)" % (self.r,degs)
        return retstr

    def __add__(self, other):
        """ Add two coords.

        @param self The left-hand coord

        @param other The right-hand coord

        @retval Coord object containing sum

        """
        return Coord(self.x + other.x, self.y + other.y)

    def __sub__(self, other):
        """ Subtract right-hand coord from left-hand.

        @param self The left-hand coord

        @param other The right-hand coord

        @retval Coord object containing sum

        """
        return Coord(self.x - other.x, self.y - other.y)

    def __eq__(self, other):
        tol = 1e-4
        return math.fabs(self.x - other.x) < tol and math.fabs(self.y - other.y) < tol


# coding: latin-1

# para executar no google colab:
# https://colab.research.google.com/drive/1rWLHIr5kqqI9BKYDBZHXXOlrkIIpR4OC?usp=sharing

from math import sqrt, log, e, sin, cos

class Bissecao:
    def __init__(self,a,b, precisao, numCasasDecimais):
        # a e b são os intervalos iniciais
        self.a = a #  início do intervalo
        self.b = b # fim do intervalo
        self.precisao = precisao
        self.numCasasDecimais = numCasasDecimais

    def funcao(self, x):
        return x**3-9*x+3

    def acharIntervalos(self):
        primeiro = True
        x = self.a
        x2 = None
        Fx2 = None
        raizes = []
        while x <= self.b:

            Fx = self.funcao(x)

            if not primeiro:
                if (Fx2 < 0 and Fx >= 0) or (Fx2 >= 0 and Fx < 0):
                    raizes.append([x2, x])

            Fx2 = Fx
            x2 = x
            primeiro = False
            x +=  1

        return raizes

    def metodoBissecao(self):
        raizes = self.acharIntervalos()

        if not raizes:
            print("Não foi possível encontrar raízes!\n\n")
        elif len(raizes) == 1:
            print("Foi encontrado 1 raiz\n\n")
        else:
            print(f"Foram encontradas {len(raizes)} raízes.\n\n")

        for raiz in raizes:
            a = round(raiz[0], self.numCasasDecimais)
            b = round(raiz[1], self.numCasasDecimais)
            #qtdEspacos = self.numCasasDecimais * 2
            iteracao = 1
            #n =  qtdEspacos + 1

            print("Iteração" , " " * self.qtdEspacos("iteracao") , "a" , " " * self.qtdEspacos("a") ,
                  "b" , " "  * self.qtdEspacos("b") , "m" , " " * self.qtdEspacos("m") , "b-a" , " " * (27) ,
                  "f(a)"  , "   "  , "f(m)" , "   " , "f(b)", sep="")

            while b-a > self.precisao:
                m = round((a+b)/2, self.numCasasDecimais)
                Fm = self.funcao(m)
                Fa = self.funcao(a)
                Fb = self.funcao(b)

                aSinal = "+" if Fa > 0 else "-"
                mSinal = "+" if Fm > 0 else "-"
                bSinal = "+" if Fb > 0 else "-"

                print(str(iteracao) , " " * self.qtdEspacos(iteracao) , str(a) , " " * self.qtdEspacos(a) , str(b) ,
                      " " *  self.qtdEspacos(b) , str(m) , " " *  self.qtdEspacos(m) , str(b-a) ,
                      " " * (30 - self.qtdCaracteres(b-a)) , str(aSinal)  , " " * 6 , str(mSinal)  , " " * 6  , str(bSinal),
                      sep='')

                if Fm * Fa < 0:
                    b = m
                elif Fm * Fb < 0:
                    a = m
                if iteracao > 50:
                    print("Limite máximo de iterações foi atingido!")
                    break

                iteracao += 1

            print(str(iteracao) , " " * self.qtdEspacos(iteracao) , str(a) , " " * self.qtdEspacos(a) , str(b) ,
                  " " *  self.qtdEspacos(b) , str(m) , " " *  self.qtdEspacos(m) , str(b-a) ,
                  " " * (30 - self.qtdCaracteres(b-a)) , str(aSinal)  , " " * 6   , str(mSinal)  , " " * 6  , str(bSinal), sep="")

            print("\n\n")

    def qtdCaracteres(self,num):
        num = str(num)
        return len(num)

    def qtdEspacos(self, num):
        num = str(num)
        return  self.numCasasDecimais * 2 + 9 - len(num)

    # def grafico(self):
    #     import matplotlib.pyplot as plt
    #     import numpy as np

    #     arrayValores = np.arange(self.a, self.b, 0.1)
    #     plt.plot(arrayValores, self.funcao(arrayValores))
    #     plt.show()

x = Bissecao(-5,5, 10**-5, 8)

#print(x.acharIntervalos())

x.metodoBissecao()

#x.grafico()


import numpy as np

def sshist(x, N=range(2, 501), SN=30):
    """
    Returns the optimal number of bins in a histogram used for density
    estimation.

    Optimization principle is to minimize expected L2 loss function between
    the histogram and an unknown underlying density function.
    An assumption made is merely that samples are drawn from the density
    independently each other.

    The optimal binwidth D* is obtained as a minimizer of the formula,
    (2K-V) / D^2,
    where K and V are mean and variance of sample counts across bins with width
    D. Optimal number of bins is given as (max(x) - min(x)) / D.

    Parameters
    ----------
    x : array_like
        One-dimensional data to fit histogram to.
    N : array_like, optional
        Array containing number of histogram bins to evaluate for fit.
        Default value = 500.
    SN : double, optional
        Scalar natural number defining number of bins for shift-averaging.

    Returns
    -------
    optN : int
        Optimal number of bins to represent the data in X
    N : double
        Maximum number of bins to be evaluated. Default value = 500.
    C : array_like
        Cost function C[i] of evaluating histogram fit with N[i] bins

    See Also
    --------
    sskernel, ssvkernel

    References
    ----------
    .. [1] H. Shimazaki and S. Shinomoto, "A method for selecting the bin size
           of a time histogram," in  Neural Computation 19(6), 1503-1527, 2007
           http://dx.doi.org/10.1162/neco.2007.19.6.1503
    """

    # determine range of input 'x'
    x_min = np.min(x)
    x_max = np.max(x)

    # get smallest difference 'dx' between all pairwise samples
    buf = np.abs(np.diff(np.sort(x)))
    dx = min(buf[buf > 0])

    # setup bins to evaluate
    N_MIN = 2
    N_MAX = min(np.floor((x_max - x_min) / (2*dx)), max(N))
    N = range(N_MIN, N_MAX+1)
    D = (x_max - x_min) / N

    # compute cost function over each possible number of bins
    Cs = np.zeros((len(N), SN))
    for i, n in enumerate(N):  # loop over number of bins
        shift = np.linspace(0, D[i], SN)
        for p, sh in enumerate(shift):  # loop over shift window positions

            # define bin edges
            edges = np.linspace(x_min + sh - D[i]/2,
                                x_max + sh - D[i]/2, N[i]+1)

            # count number of events in these bins
            ki = np.histogram(x, edges)

            # get mean and variance of events
            k = ki[0].mean()
            v = np.sum((ki[0] - k)**2) / N[i]

            Cs[i, p] = (2*k - v) / D[i]**2

    # average over shift window
    C = Cs.mean(axis=1)

    # get bin count that minimizes cost C
    idx = np.argmin(C)
    optN = N[idx]
    optD = D[idx]
    edges = np.linspace(x_min, x_max, optN)

    return optN, optD, edges, C, N