import numpy as np
from ..exceptions import NotFittedError
from ..utils import check_features, check_target

class LinearRegression(object):
    """Linear regression estimator.

    Can be solved in closed form using the normal equation or singular
    value decomposition. It's also possible to fit using a batch
    gradient descent algorithm.

    Attributes:
        learning_rate: Rate of update for gradient descent at
        each iteration. Not used for other solving methods (float).
        num_iterations: Number of iterations for gradient descent (int).
        save_cost: Whether to save or not the cost of each iteration.
        Only used for gradient descent (boolean).
        grad_descent_cost: List with the cost for each iteration when
        using gradient descent (list of floats).
        parameters: nd array with the model parameters (theta).
    """

    def __init__(self, solving_method='svd', learning_rate=0.01,
                 num_iter=1000, save_cost=False):
        self.solving_method = solving_method
        self.learning_rate = learning_rate
        self.num_iterations = num_iter
        self.save_cost = save_cost

        solvers = ['svd', 'normal_equation', 'gradient_descent']
        if self.solving_method not in solvers:
            raise ValueError("solving_method must be one of: ", solvers)

    def fit(self, x, y):
        """Fit a linear regression model to features x and target y.

        Arguments:
            x: Features - nd array with shape (m_samples, n_features).
            If you have a pandas Dataframe use df.values.
            y: Target values. Can be a one or two dimensional numpy
            array with shape (m_samples,) or (m_samples, 1)
        """
        check_features(x)
        check_target(y)
        x = np.insert(x, 0, 1, axis=1)  # add bias
        y = y.reshape(-1, 1) if y.ndim == 1 else y

        if self.solving_method == 'svd':
            self.parameters = np.linalg.pinv(x) @ y
        elif self.solving_method == 'normal_equation':
            # Normal equation: inv(X'*X) * X' * Y
            self.parameters = np.linalg.pinv(x.T @ x) @ x.T @ y
        else:
            self.parameters = np.zeros(shape=(x.shape[1], 1))
            self.batch_gradient_descent(x, y)
        return self

    def predict(self, x):
        """Return predictions for ndarray with shape (m_samples, n_features)."""
        check_features(x)
        x = np.insert(x, 0, 1, axis=1)  # add bias
        try:
            return self.hypothesis(x)
        except AttributeError:
            raise NotFittedError("You must fit before making predictions.")

    def hypothesis(self, x):
        """Hypothesis for linear regression (ax + b)."""
        return x @ self.parameters

    def gradient_function(self, x, y, predictions=None):
        """Compute the gradient with the current parameters."""
        if predictions is None:
            predictions = self.hypothesis(x)
        return x.T @ (predictions - y)

    def cost_function(self, x, y, predictions=None):
        """Return the cost for the current parameters using MSE."""
        if predictions is None:
            predictions = self.hypothesis(x)
        squared_error = np.sum(np.square(predictions - y))
        return squared_error / (2 * x.shape[0])

    def batch_gradient_descent(self, x, y):
        """Batch gradient descent implementation (vectorized)."""

        self.grad_descent_cost = []
        for _ in range(self.num_iterations):
            # Make predictions and calculate gradient
            predictions = self.hypothesis(x)
            gradient = self.gradient_function(x, y, predictions)

            # Update current parameters
            self.parameters = self.parameters - self.learning_rate / x.shape[0] * gradient
            if self.save_cost:
                self.grad_descent_cost.append(self.cost_function(x, y, predictions))

lr = LinearRegression()


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

def bernoulli_posterior(data, prior):
	n_1 = sum(data)
	n_2 = len(data) - n_1
	x = np.arange(0,1.01,step=.01)
	y = beta.pdf(x, prior[0] + n_1 - 1, prior[1] + n_2 - 1)
	plt.plot(x, y)
	plt.show()
	return

def problem1():
	data = np.fromfile('trial.csv', dtype=int, sep='\n')
	bernoulli_posterior(data,np.array([8., 2.]))

def multinomial_beta(alpha):
	return np.prod(np.array([math.gamma(alpha[i]) for i in xrange(len(alpha))]))/math.gamma(np.sum(alpha))

def multinomial_posterior(data, prior):
	categories = np.sort(list(set(data)))
	n = len(categories)
	sums = np.zeros(n)
	for i in xrange(n):
		sums[i] = sum(data==categories[i])
	return prior + sums

def problem2():
	with open('fruit.csv', 'r') as fruit:
		data = np.array([line.strip() for line in fruit])
	multinomial_posterior(data, np.array([5., 3., 4., 2., 1.]))

def invgammapdf(x, alpha, beta):
	alpha = float(alpha)
	beta = float(beta)
	if not np.isscalar(x):
		return (beta**alpha / math.gamma(alpha))*np.array([(xi**(-alpha - 1))*math.exp(-beta/xi) for xi in x])
	else:
		return (beta**alpha / math.gamma(alpha))*(x**(-alpha - 1))*math.exp(-beta/x)

def mean_posterior(data, prior, variance):
	n = float(len(data))
	sample_mean = np.mean(data)
	mu_0 = prior[0]
	sigma2_0 = prior[1]
	posterior_mean = ((mu_0*variance)/n + sample_mean*sigma2_0)/(variance/n + sigma2_0)
	posterior_variance = 1./(n/variance + 1./sigma2_0)
	return posterior_mean,posterior_variance

def problem3():
	data = np.fromfile('examscores.csv', dtype=float, sep='\n')

	posterior_mean, posterior_variance = mean_posterior(data, np.array([74., 25.]), 36.)
	x = np.arange(0, 100.1, step=0.1)
	y = norm.pdf(x, loc=posterior_mean, scale=np.sqrt(posterior_variance))
	plt.plot(x, y)
	plt.show()

def variance_posterior(data, prior, mean):
	n = float(len(data))
	alpha = prior[0]
	beta = prior[1]
	posterior_alpha = alpha + n/2.
	posterior_beta = beta + np.dot(data-mean, data-mean)/2.
	return posterior_alpha, posterior_beta

posterior_alpha, posterior_beta = variance_posterior(data, np.array([2., 25.]), 62.)
x = np.arange(0.1, 100.1, step=0.1)
y = invgammapdf(x, posterior_alpha, posterior_beta)
plt.plot(x, y)
plt.show()


# -*- coding: utf-8 -*-
"""
Created on Thu Sep 23 01:25:36 2021

@author: Mahfuz_Shazol
"""

# frommula A^+ =VD^+ U^T

import numpy as np

A=np.array([
            [-1,2],
            [3,-2],
            [5,7]
           ])

U ,d ,VT =np.linalg.svd(A)

D=np.diag(d)
print(D)

D_inv=np.linalg.inv(D)
print(D_inv)

print(A.shape[0])
print(A.shape[1])

D_plus=np.zeros((3,2)).T
print(D_plus)

D_plus[:2,:2]=D_inv
print(D_plus)

result=np.dot(VT.T,np.dot(D_plus,U.T))

print('A^+',result)

#numpy has build in function
result=np.linalg.pinv(A)
print(result)


# Program 02e: Numerical and truncated series solutions.
# See Figure 2.6.

from scipy.integrate import odeint
import matplotlib.pyplot as plt
import numpy as np

def ODE2(X, t):
    x = X[0]
    y = X[1]
    dxdt = y
    dydt = x - t ** 2 * y
    return [dxdt, dydt]

X0 = [1, 0]
t = np.linspace(0, 10, 1000)

sol = odeint(ODE2, X0, t)

x = sol[:, 0]
y = sol[:, 1]

fig, ax = plt.subplots()
ax.plot(t, x, label='Numerical')
ax.plot(t, 1 + t**2 / 2 + t**4 / 24, 'r-', label='Truncated series')
plt.xlabel('t', fontsize=15)
plt.ylabel('x', fontsize=15)
plt.tick_params(labelsize=15)
plt.xlim(0, 4)
plt.ylim(0, 4)

ax.legend(loc='lower center', shadow=True)

plt.show()


"""
Created on Dec 6, 2021
Author: Haoming(Hammond) Liu
Email: hl3797@nyu.edu
"""

import os
import numpy as np
from scipy.linalg import rq

# check input file & load points
assert os.path.isfile('world.txt')
assert os.path.isfile('image.txt')
world_pts = np.loadtxt('world.txt')
image_pts = np.loadtxt('image.txt')
# print(world_pts.shape, image_pts.shape)

# concatenate ones
N = world_pts.shape[1]
world_pts = np.vstack((world_pts, np.ones((1, N))))
image_pts = np.vstack((image_pts, np.ones((1, N))))
print('world points:', world_pts, sep='\n')
print('image points:', image_pts, sep='\n')

# constracut matrix A
A_rows = []
zero_item = np.zeros((1, 4))
for i in range(N):
    xi, yi, wi = tuple(image_pts.T[i])
    Xi = world_pts.T[i].reshape(1, 4)
    A_rows.append(np.hstack((zero_item, -wi*Xi, yi*Xi)))
    A_rows.append(np.hstack((wi*Xi, zero_item, -xi*Xi)))
A = np.vstack(A_rows)
print('Matrix A: shape =', A.shape)
print(A)

# solve P using SVD
_, s, v = np.linalg.svd(A)
P = v[np.argmin(s)].reshape(3, 4)
print('Matrix P: shape =', P.shape)
print(P)
inhomo = lambda x: x / x[-1]
verify = np.matmul(P, world_pts)
print('verify proj: shape = image_pts =', image_pts.shape)
print(image_pts - inhomo(verify))

# solve C using SVD (null-space of P)
_, s, v = np.linalg.svd(P)
C1 = inhomo(v[-1].reshape(4, 1))[:-1].T.squeeze()
print('Projection Center C: shape =', C1.shape)
print(C1)

# alternative route
r, K = np.linalg.qr(P.T)
R, t = r[:-1].T, r[-1].T
C2 = np.linalg.solve(-R, t)
print('Alternative Route:')
print(C2)


import math

import numpy
from numpy.linalg import norm
from scipy.fft import dctn

from aydin.analysis.resolution_estimate import resolution_estimate

def snr_estimate(image, display_images: bool = False) -> float:
    """Estimates the signal to noise ratio of an image in DB.

    A value of 0 means that the signal and noise have roughly the same energy,
    a negative value means that the noise is stronger than the signal,
    and reciprocally, a positive value means that the signal is stronger
    than the noise.

    Parameters
    ----------
    image : numpy.typing.ArrayLike
        Image to compute SNR estimate for.

    display_images: bool
        If true displays the spectrum in a napari window.

    Returns
    -------
    Returns an estimate of the image's signal-to-noise ratio in dB.
    """

    # First we estimate resolution:
    frequency, image = resolution_estimate(image)

    # import napari
    # viewer = napari.Viewer()
    # viewer.add_image(image, name='clean_image')
    # napari.run()

    # cast and copy:
    image = image.astype(numpy.float32)

    # Normalise:
    image -= image.mean()
    variance = image.var()
    if variance > 0:
        image /= variance

    # Compute the DCT:
    image_dct = dctn(image, workers=-1)

    # Compute frequency map:
    f = numpy.zeros_like(image)
    axis_grid = tuple(numpy.linspace(0, 1, s) for s in image.shape)
    for x in numpy.meshgrid(*axis_grid, indexing='ij'):
        f += x**2
    f = numpy.sqrt(f)

    # define two domains:
    signal_domain = f <= frequency
    noise_domain = f > frequency

    # First we measure the energy of both signa and noise:
    signal_energy = norm(image_dct[signal_domain]) ** 2
    noise_energy = norm(image_dct[noise_domain]) ** 2

    if display_images:
        import napari

        viewer = napari.Viewer()
        viewer.add_image(image, name='image')
        viewer.add_image(numpy.log1p(numpy.abs(image_dct)), name='image_dct')

        image_dct_signal = image_dct.copy()
        image_dct_signal[noise_domain] = 0
        viewer.add_image(
            numpy.log1p(numpy.abs(image_dct_signal)), name='image_dct_signal'
        )

        image_dct_noise = image_dct.copy()
        image_dct_noise[signal_domain] = 0
        viewer.add_image(
            numpy.log1p(numpy.abs(image_dct_noise)), name='image_dct_noise'
        )
        napari.run()

    # However, this is an underestimate of the noise, because we assume that
    # the noise is uniformly distributed in frequency space. Therefore, we need
    # to correct this first estimate. For this we need the 'volume, in frequency
    # space of both domains:

    signal_domain_volume = numpy.sum(signal_domain) / image_dct.size
    noise_domain_volume = 1 - signal_domain_volume

    # We re-estimate the noise energy assuming the same density over the whole
    # spectrum:
    corrected_noise_energy = noise_energy / noise_domain_volume

    # For the signal energy we remove the energy that comes from the noise:
    corrected_signal_energy = (
        signal_energy - signal_domain_volume * corrected_noise_energy
    )

    # We can't let the signal energy to go below zero:
    corrected_signal_energy = max(1e-16, corrected_signal_energy)

    # Signal to noise ratio in dB:
    noise_ratio = 10 * math.log10(corrected_signal_energy / corrected_noise_energy)

    return noise_ratio


# Generates x,y points in a Fermat spiral
# Bryan Miller
# theta = 137.508*np.pi/180., golden angle
# b = number of spirals
# a = scale factor, default gives positions in degrees

import numpy as np

# Calculate points in a Fermat spiral
def fermat(n_point,a=0.03,b=1.0,theta=2.399963):
    # local variable with the correct type
    l_npt = int(n_point)
    l_a = float(a)
    l_b = float(b)
    l_theta = float(theta)

    x = np.zeros(n_point)
    y = np.zeros(n_point)

    for ii in range(l_npt):
        l_ii = float(ii)
        x[ii] = l_a*np.sqrt(l_ii)*np.cos(l_b*l_ii*l_theta)
        y[ii] = l_a*np.sqrt(l_ii)*np.sin(l_b*l_ii*l_theta)

    return x,y

# Determine scale factor needed to produce a given offset in n_point points
def fermat_scale(n_point,offset,b=1.0,theta=2.399963):
    # local variable with the correct type
    l_npt = float(n_point)
    l_offset = float(offset)
    l_b = float(b)
    l_theta = float(theta)

    a = l_offset/(np.sqrt(l_npt*(np.cos(l_b*l_npt*l_theta)**2 + np.sin(l_b*l_npt*l_theta)**2)))

    return a


import numpy as np
import math

# simplex algorithm
'''
Need a super class that takes constants into account in objFun
'''
class Simplex(object):
	'''
	max 3x+2y
	s.t. x+2y <=4
		 x-y <= 1
		 x,y >= 0

	with slack variables, translated into
	c = [3, 2]
	A = [[1,  2],
		 [1, -1]]
	b = [4, 1]

	For now, assume proper c, A, b inputs

	for min f(x), use duality of simplex
	'''
	'''
	method based on multiple sources:
	https://www.youtube.com/watch?v=XK26I9eoSl8
	https://hubpages.com/technology/Simplex-Algorithm-in-Python
	https://jeremykun.com/2014/12/01/
					linear-programming-and-the-simplex-algorithm/
	https://www.cs.cmu.edu/afs/cs/academic/
					class/15780-s16/www/slides/linear_prog.pdf
	MAIN SOURCE: https://www.youtube.com/watch?v=BdtdYlUIXak
	MAIN SOURCE: http://web.mit.edu/15.053/www/AMP-Chapter-04.pdf

	tableu from above example should look like
	x  y  s1  s2  P  b
	------------------
	1  2   1   0  0  4   Constraint Rows
	1  -1  0   1  0  1
	------------------
	-3 -2  0   0  1  0   ObjFun row
	'''
	'''
	Things to Consider:
	- objective function has constant number
	- infeasible solution
	- infinite solution

	Currently only handles feasible single point solution
	'''
	def __init__(self, c, A, b, maxi):
		self.varLen = len(c) # number of variables
		self.conLen = len(b) # number of slack variables(aka # of constraints)
		#np.concatenate((x, np.identity(len(x))),axis=1)
		self.maxi = maxi

		bCol = np.array([b + [0]], dtype=float) # assumes no constant val in objfun
		varTable = np.array(A+[c], dtype=float)
		mainTable = np.concatenate((varTable, bCol.T),axis=1)
		if not self.maxi: # minimization prob as dual prob
			mainTable = mainTable.T

		# split mainTable into table with factors and table with constants
		bCol = np.array([mainTable[:,-1]])
		if self.maxi:
			factorTable = mainTable[:,:self.varLen]
			slckAndP = np.identity(self.conLen+1) #num of slack = num of constraints
		else:
			factorTable = mainTable[:,:self.conLen]
			slckAndP = np.identity(self.varLen+1)
		# multiply -1 to objfun row
		factorTable[-1,:] *= -1

		self.tableu = np.concatenate((factorTable,slckAndP,bCol.T),axis=1)

	# if any variable with negative factor, can improve
	def canImprove(self):
		for varFactor in self.tableu[-1]: #objFun
			if varFactor < 0:
				return True
		return False

	# find pivRow & pivCol; same method for both maxi and mini
	def findPivot(self):
		# pivotCol is col with most negative factor in objfun
		minFact = 0 # minimum factor of objfun
		objFun = self.tableu[-1]
		for col in range(len(objFun)-2): # exclude P and b col
			if objFun[col] < minFact:
				minFact = objFun[col]
				self.pivCol = col
				#self.pivColSet = (self.pivColSet).union([col])

		ratios = []
		for row in range(len(self.tableu)-1): # exclude objfun row
			if (abs(self.tableu[row][self.pivCol]) > 0
				and self.tableu[row][-1]/self.tableu[row][self.pivCol] > 0):
				constant = self.tableu[row][-1]
				ratios.append(constant/self.tableu[row][self.pivCol])
			else: ratios.append(float("inf")) #just a place holder
		# pick row index minimizing the quotient
		self.pivRow = ratios.index(min(ratios))

	#destructively change tableu
	def pivot(self):
		pivR, pivC = self.pivRow, self.pivCol
		# divide whole pivRow so factor @ pivRow&Col = 1
		self.tableu[pivR] = np.divide(self.tableu[pivR], float(self.tableu[pivR][pivC]))

		# subtract the rest with pivRow*factor
		notPivRows = set(list(range(len(self.tableu)))).difference(set([pivR]))
		for row in notPivRows:
			factor = self.tableu[row][pivC]
			self.tableu[row] -= np.dot(self.tableu[pivR], factor)

	def primalSolution(self):
		# initialize values of all variables
		primal = [0]*self.varLen
		# find basic variable solutions and record them
		for col in range(self.varLen):
			oneFound = False
			varI = 0
			varRow = 0
			for row in range(len(self.tableu)):
				if self.tableu[row][col] == 1:
					if not oneFound: oneFound, varI, varRow = True, col, row
					else:
						oneFound = False
						break
			if oneFound: primal[varI] = self.tableu[varRow][-1]
		return primal

	def dualSolution(self):
		dual = [0]*self.varLen
		# for every "slack variables" in dual problem
		for col in range(self.conLen, self.conLen+self.varLen):
			objFunRow = self.tableu[-1]
			# solution of primal problem is the number at objfunrow
			newVal = objFunRow[col]
			dual[col-self.conLen] = newVal
		return dual

	def objectiveValue(self):
		return self.tableu[-1][-1]

	def simplex(self):
		#np.set_printoptions(precision=2)
		#print(self.tableu)
		while self.canImprove():
			self.findPivot()
			self.pivot()
			#print(self.tableu)
		if self.maxi: solution = self.primalSolution()
		else: solution = self.dualSolution()
		return solution, self.objectiveValue()


from __future__ import division
from __future__ import print_function

import numpy as np
import matplotlib

matplotlib.use('TkAgg')
import matplotlib.pyplot as plt

np.random.seed(0)  # set the random seed for reproducibility

def generate_sample(xmin, xmax, sample_size):
    x = np.linspace(start=xmin, stop=xmax, num=sample_size)
    pix = np.pi * x
    target = np.sin(pix) / pix + 0.1 * x
    noise = 0.05 * np.random.normal(loc=0., scale=1., size=sample_size)
    return x, target + noise

def calc_design_matrix(x, c, h):
    return np.exp(-(x[None] - c[:, None]) ** 2 / (2 * h ** 2))

def shuffle_two_array(x,y):
    shuffled_x = np.array([])
    shuffled_y = np.array([])
    permutation = np.random.permutation(len(x))
    for i in permutation:
        shuffled_x = np.append(shuffled_x,x[i])
        shuffled_y = np.append(shuffled_y,y[i])
    return (shuffled_x,shuffled_y)

def cross_validation (num,x,y) :
    best_l = None
    best_h = None
    shuffled_x,shuffled_y = shuffle_two_array(x,y)
    x_c = np.array_split(shuffled_x, num)
    y_c = np.array_split(shuffled_y, num)
    best_validation = np.inf
    for i in range(10):
        l = 10 ** (4-i)
        for j in range(10):
            h = 10 ** (4-j)
            validation_value = 0
            for n in range (num):
                x_train = np.array([])
                for le in range(len(x_c)):
                    if(le != n):
                        x_train = np.append(x_train,x_c[le])
                y_train = np.array([])
                for le in range(len(y_c)):
                    if(le != n):
                        y_train = np.append(y_train,y_c[le])
                x_test = x_c[n]
                y_test = y_c[n]
                k = calc_design_matrix(x_train, x_train, h)
                theta = np.linalg.solve(
                    k.T.dot(k) + l * np.identity(len(k)),
                    k.T.dot(y_train[:, None]))
                k_test = calc_design_matrix(x_train, x_test, h)
                pred_list = k_test.dot(theta)
                validation_value = validation_value + np.sum((y_test - pred_list.T) ** 2)
            validation_value = validation_value / num
            if (validation_value < best_validation) :
                best_validation = validation_value
                best_l = l
                best_h = h
    return (best_l,best_h)

# create sample
sample_size = 50
xmin, xmax = -3, 3
x, y = generate_sample(xmin=xmin, xmax=xmax, sample_size=sample_size)

# k-fold cross-validation
best_l, best_h = None, None

# --- implement here ---

best_l,best_h = cross_validation(5,x,y)

# --- end implement ---

print('Best (l, h): ({}, {})'.format(best_l, best_h))

#
# visualization
#

# calculate design matrix
k = calc_design_matrix(x, x, best_h)

# solve the least square problem
theta = np.linalg.solve(
    k.T.dot(k) + best_l * np.identity(len(k)),
    k.T.dot(y[:, None]))

# create data to visualize the prediction
X = np.linspace(start=xmin, stop=xmax, num=5000)
K = calc_design_matrix(x, X, best_h)
prediction = K.dot(theta)

plt.clf()
plt.scatter(x, y, c='green', marker='o')
plt.plot(X, prediction)
plt.savefig('ML1-homework1.png')


# Ajuste do circuito RC
import numpy as np
import matplotlib.pyplot as plt

def aj_lin(xi, yi):
    '''
    Realiza o ajuste linear de pontos em uma reta de ajuste no formato "y = ax + b"
    :param xi: coordenadas x dos pontos
    :param yi: coordenadas y dos pontos
    :return: coeficiente angular "a" e coeficiente linear "b" da reta de ajuste
    '''
    n = len(xi)
    mxy = sum(xi*yi)/n
    mx = sum(xi)/n
    my = sum(yi)/n
    mqx = sum(xi**2)/n
    a = (mxy - (mx*my))/(mqx - (mx**2))
    b = ((mqx*my) - (mx*mxy))/(mqx - (mx**2))
    return a, b

t, v = np.loadtxt('dados-rc.txt', unpack=True)
logv = np.log(v[1:])
art = np.linspace(0, 1.9)
cof = aj_lin(t[1:], logv)
v0, c = np.exp(cof[1]), 1/(10*cof[0])

vt = lambda tt: cof[0]*tt + cof[1]

texto = f'a = {cof[0]:.3f}\nb = {cof[1]:.3f}\nV={v0:.3f}.exp(-t/R.{-c:.3f})'

plt.scatter(t[1:], logv, s=30, marker='.', c='k')
plt.plot(art, vt(art), 'magenta')
plt.text(1, 1.5, texto, bbox=dict(boxstyle='square', ec='k', color='white'))
plt.grid()
plt.title('Descarga do Capacitor')
plt.xlabel('t(s)')
plt.ylabel('ln(V)')
#plt.show()
plt.savefig('atv_rc.jpeg')


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Special math functions
======================
Common special functions to be used across Sympy implemented models

"""

from sympy import besselj, bessely, legendre, I, sqrt, pi
from sympy import symbols

p,m,v,n,z = symbols('p m v n z')

# spherical Bessel function
sph_bessel1 = besselj(n+1/2,z)*sqrt(pi/(2*z))
# sphericl Neumann function
sph_bessel2 = bessely(n+1/2,z)*sqrt(pi/(2*z))
# spherical Hankel function of the second kind
sph_hankel2 = sph_bessel1 - I*sph_bessel2

h2_nz = sph_bessel1 - I*sph_bessel2 # more compact notation.

# This function can actuall be replaced by the inbuilt 'assoc_legendre' with varying mileage
# upon lambdification
# pmvz version of legendre function (Appendix II of Beranek & Mello 2012, eqn. 63)
# this is the equivalent of Latex: P^{m}_{v}(z)
legendre_mvz = ((-1)**m)*((1-z**2)**(m/2))*legendre(v,z).diff((z,m))


import numpy as np

H = 1 / np.sqrt(2) * np.array([[1.0, 1.0],
                               [1.0, -1.0]], dtype=np.complex64)

# Pauli X
X = np.array([[0, 1.0],
              [1.0, 0]], dtype=np.complex64)

# Pauli Y
Y = np.array([[0, -1j],
              [1j, 0]], dtype=np.complex64)

# Pauli Z
Z = np.array([[1.0, 0],
              [0, -1.0]], dtype=np.complex64)

def phase_shift(phi: np.real):
    return np.array([[1.0, 0],
                     [0, np.e ** (1.0j * phi)]], dtype=np.complex64)

# S is a pi/2 rotation about the z-axis
S = phase_shift(np.pi / 2)
Sdg = phase_shift(-np.pi / 2)

# T is a pi/4 rotation about the z-axis
T = phase_shift(np.pi / 4)
Tdg = phase_shift(-np.pi / 4)

# Cx is a controlled NOT gate.
# When applied to two qubits a rotation of pi/2 radians
# is applied to the target qubit if the control qubit is |1⟩
# |a, b⟩ --> |a, a ⊗ b⟩
# |00⟩ --> |00⟩, |01⟩ --> |01⟩, |10⟩ --> |11⟩, |11⟩ --> |10⟩
Cx = np.array([[1, 0, 0, 0],
               [0, 1, 0, 0],
               [0, 0, 0, 1],
               [0, 0, 1, 0]], dtype=np.complex64)


from numba import jit, vectorize, guvectorize, float64, complex64, int32, float32
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import colors

norm =colors.PowerNorm(0.9)
#From https://www.ibm.com/developerworks/community/blogs/jfp/entry/How_To_Compute_Mandelbrodt_Set_Quickly?lang=en
@jit(int32(complex64, int32))
def mandelbrot(c,maxiter):
    nreal = 0
    real = 0
    imag = 0
    for n in range(maxiter):
        nreal = real*real - imag*imag + c.real
        imag = 2* real*imag + c.imag
        real = nreal;
        if real * real + imag * imag > 4.0:
            return n
    return 0

@guvectorize([(complex64[:], int32[:], int32[:])], '(n),()->(n)',target='parallel')
def mandelbrot_numpy(c, maxit, output):
    maxiter = maxit[0]
    for i in range(c.shape[0]):
        output[i] = mandelbrot(c[i],maxiter)

def mandelbrot_set2(xmin,xmax,ymin,ymax,width,height,maxiter):
    r1 = np.linspace(xmin, xmax, width, dtype=np.float32)
    r2 = np.linspace(ymin, ymax, height, dtype=np.float32)
    c = r1 + r2[:,None]*1j
    n3 = mandelbrot_numpy(c,maxiter)
    return (r1,r2,n3.T)

xmin, xmax, xn = -2.25, +0.75, 3000/2
ymin, ymax, yn = -1.25, +1.25, 3000/2
maxiter = 1000

r1,r2,M = mandelbrot_set2(xmin,xmax,ymin,ymax,int(xn),int(yn),maxiter)
fig,ax = plt.subplots(figsize=(12,8))
ax.set_axis_off()
ax.set_title(r"The Mandelbrot Set for $Z_{n + 1} = Z_n^2 + c$ where $c \in \mathbb{C}$")
ax.imshow(M,
                    aspect='equal',
                    cmap='nipy_spectral',
                    norm=norm,
                    interpolation='spline36')
plt.show()
#plt.savefig('/Users/Llewelyn_home/Dropbox/Computation in Python/Chaos and nonlinear/Mandelbrot2.png')


from random import *
from math import sqrt
import matplotlib.pyplot as plt
import numpy as np
n =int(input("Enter the total number of points inside the square or cube "))
pi_true=np.pi

def pi_2D(n):
    inpoint1=0
    for i in range(n):
        x=random()
        y= random()
        if sqrt(x*x+y*y)<=1:
            inpoint1+=1

        pi_2D=4*inpoint1/n

    return pi_2D
    # print("number of points inside the sphere are ",inpoint1)
def pi_3D(n):
    inpoint2=0
    for j in range(n):
        x=random()
        y= random()
        z=random()
        if sqrt(x*x+y*y+z*z)<=1:
            inpoint2+=1

        pi_3D=6*inpoint2/n

    return pi_3D
    # print("num+ber of points inside the circle are ",inpoint2)

# print("The difference between actual value and obtained value ",error1)
print("The value of pi from 2D circle is= ",pi_2D(n))
print("-----------------------------------------------------")

# print("The difference between actual value and obtained value ",error2)
print("The value of pi from 3D sphere is= ",pi_3D(n))

list_n=[]
list_err2D=[]
list_err3D=[]

for k in range(7):
    n=pow(10,k)
    err2D=abs(pi_true-pi_2D(n))
    err3D=abs(pi_true-pi_3D(n))
    list_n.append(n)
    list_err2D.append(err2D)
    list_err3D.append(err3D)

plt.plot(list_n,list_err2D,marker="o",label="Variation")
plt.plot(list_n,list_err3D,marker="o",label="Variation")
plt.title(" Deviation from the true value of pi ")
plt.xlabel("n")
plt.ylabel("Error")
plt.legend()
plt.show()
'''
x=range(n)
plt.title("plot between error and points inside the square")
plt.plot(x,listy1)
plt.plot(x,listy2)
plt.xlabel("n")
plt.ylabel("error")
plt.show()
'''


## import numpy, panda, statsmodels
import pandas as pd
import numpy as np
import statsmodels.api as sm
import matplotlib as mpl
mpl.use('TkAgg') # backend adjustment
import matplotlib.pyplot as plt
from math import sqrt
import random
import seaborn as sns

class OLB_bias:
    def mystats(self,x):
        # isna function
        p = np.where(np.isnan(x))
        if len(p[0]) > 0:
            x = np.delete(x, p)
            return x
        else:
            pass

        m = np.mean(x)
        n = len(x)
        s = np.std(x)
        skew = sum((x - m)**3 /s**3) / n
        kurt = sum((x - m)**4 / s**4) / n - 3
        return {'n':n,
                'mean':m,
                'stdev':s,
                'skewness':skew,
                'kurtosis':kurt}

    def OLS_bias(self,M,n,a,b):
        np.random.seed(1)
        x = np.random.randn(n)
        e = np.zeros((M,n))
        y = np.zeros((M,n))
        ahat = np.zeros((M,1))
        bhat = np.zeros((M,1))
        vara = np.zeros((M,1))
        varb = np.zeros((M,1))
        i = 0

        for i in range(0, M):
            e[i,:] = np.random.randn(n)
            y[i,:] = a+b*x+e[i,:]
            x_experience = sm.add_constant(x)
            model1 = sm.OLS(y[i,:], x_experience)
            result1 = model1.fit()
            ahat[i] = result1.params[0]
            bhat[i] = result1.params[1]
            vara[i] = result1.bse[0]
            vara[i] = result1.bse[1]

        d = {'ahat':ahat.ravel(),
             'bhat':bhat.ravel(),
             'vara':vara.ravel(),
             'varb':varb.ravel()}
        datafour = pd.DataFrame(data=d)
        print datafour
        statistics = []
        for i in datafour:
            u = OLB_bias.mystats(self,datafour[i])
            statistics.append(u)
        print statistics

        self.bias_a = datafour['ahat']
        self.bias_b = datafour['bhat']
        d = {'bias_a': self.bias_a.ravel(),
             'bias_b':self.bias_b.ravel()}
        biasab = pd.DataFrame(data=d)
        #plots
        plt.hist(ahat, 100, facecolor="red")
        plt.xlabel('Estimates of a')
        plt.ylabel('Frequency')
        plt.title('Histogram of estimates a')
        plt.savefig('plot4.png')
        plt.clf()
        plt.hist(bhat, 100, facecolor="blue")
        plt.xlabel('Estimates of b')
        plt.ylabel('Frequency')
        plt.title('Histogram of estimates b')
        plt.savefig('plot5.png')
        plt.clf()
        #density
        sns.kdeplot(np.array(ahat.ravel()), bw=0.5)
        plt.title('Kernel density of a estimates')
        plt.savefig('plot6.png')
        plt.clf()
        sns.kdeplot(np.array(bhat.ravel()), bw=0.5)
        plt.title('Kernel density of b estimates')
        plt.savefig('plot7.png')
        plt.clf()

        return biasab

    # OLS_ebias
    def OLS_ebias(self,M, n, a, b):
        bias = OLB_bias.OLS_bias(self, M, n, a, b)
        self.a = self.bias_a
        self.b = self.bias_b
        d = {'bias_a': self.a.ravel(),
             'bias_b': self.b.ravel()}
        Ebias = pd.DataFrame(data=d)

    #OLS_consistent
    def OLS_consistent(self,M,n,a,b,I):

        ee = np.zeros((I,2))
        for t in range(0, I):
            Ebias = OLB_bias.OLS_ebias(self,M,n,a,b)
            ee[t,0]= self.a
            ee[t,1] = self.b
            n=n+300
        plt.plot(ee[:,0], c='red')
        plt.xlabel('loops of adding 300 observations')
        plt.title('Trend of variance ahat')
        plt.savefig('plot8.png')
        plt.clf()
        plt.plot(ee[:,1], c='blue')
        plt.xlabel('loops of adding 300 observations')
        plt.title('Trend of variance ahat')
        plt.savefig('plot9.png')
        plt.clf()
        print ee

olb = OLB_bias()
mout = olb.OLS_bias(1000, 100, 1.5, 0.7)
olb.OLS_consistent(500,300,1.5,0.7,10)

'''
    for(i in 1:M)
    {
      e[i,]<-rnorm(n)
      y[i,]<-a+b*x+e[i,]
      model<-lm(y[i,]~x)
      ahat[i]<-model$coefficient[1]
      bhat[i]<-model$coefficient[2]
      vara[i]<-summary(model)$coefficient[1,2]
      varb[i]<-summary(model)$coefficient[2,2]
    }
    datafour<-data.frame(ahat,bhat,vara,varb)
    statistics<-sapply(datafour,mystats)
    print(statistics)

    bias_a<-datafour[1]#-a
    bias_b<-datafour[2]#-b
    biasab<-data.frame(bias_a,bias_b)
    colnames(biasab)<-c("bias_a","bias_b")

    par(mfrow=c(2,2))
    hist(datafour$ahat,breaks=100,col="red",xlab="estimates of a",main="Histogram of estimates a")
    hist(datafour$bhat,breaks=100,col="blue",xlab="estimates of a",main="Histogram of estimates b")
    kd_a<-density(datafour$ahat)
    kd_b<-density(datafour$bhat)
    plot(kd_a,main="Kernel density of a estimates",col="red")
    plot(kd_b,main="Kernel density of b estimates",col="blue")

    return(biasab)
    #return(statistics)
}

mout<-OLS_bias(1000,100,1.5,0.7)

##OLS_consistent
OLS_consistent<-function(M,n,a,b,I)
{
    OLS_ebias<-function(M,n,a,b)
    {
      bias<-OLS_bias(M,n,a,b)
      a<-var(bias$bias_a)
      b<-var(bias$bias_b)
      Ebias<-data.frame(a,b)
    }

    ee<-matrix(nrow=I,ncol=2)
    for(t in 1:I)
    {
      Ebias<-OLS_ebias(M,n,a,b)
      ee[t,1]<-Ebias$a
      ee[t,2]<-Ebias$b
      n<-n+300
    }

    plot(ee[,1],xlab="loops of adding 300 observations",ylab=" ",main="Trend of variance ahat",col="red")
    plot(ee[,2],xlab="loops of adding 300 observations",ylab=" ",main="Trend of variance bhat",col="blue")
    ee
}

OLS_consistent(500,300,1.5,0.7,10)

'''


import numpy as np
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from sklearn import decomposition
from sklearn import datasets
from sklearn.preprocessing import StandardScaler
from scipy import linalg as LA

def run_pca_np(x):
    #centering the data
    x -= np.mean(x, axis = 0)

    cov = np.cov(x, rowvar = False)

    evals , evecs = LA.eigh(cov)
    idx = np.argsort(evals)[::-1]
    evecs = evecs[:,idx]
    evals = evals[idx]

    a = np.dot(x, evecs)
    return a

def run_pca(x, n_components=3):
    scaler = StandardScaler(copy=True, with_mean=True, with_std=True)
    # print("Before normalization")
    # mean = np.mean(x)
    # variance = np.var(x)
    # print(mean)
    # print(variance)
    scaler.fit(x)
    # print(scaler.mean_)
    x_std = scaler.transform(x)
    # print("After normalization")
    # mean_std = np.mean(x_std)
    # variance_std = np.var(x_std)
    # print(mean_std)
    # print(variance_std)
    # print(x_std)
    pca = decomposition.PCA(n_components)
    # https://stats.stackexchange.com/questions/235882/pca-in-numpy-and-sklearn-produces-different-results
    # input the standarized data with mean 0 and var 1 to the PCA
    result = pca.fit_transform(x_std)
    # we can just return this
    # but we can normalize
    # the result too
    # scaler.fit(result)
    # print(scaler.mean_)
    # result_std = scaler.transform(result)
    return result

if __name__ == "__main__":
    x = np.random.random_sample((18, 3209))
    print(x)
    print(x.shape)
    result = run_pca(x)
    print(result)
    print(result.shape)


"""
This file runs BlackScholes algorithm on GPU
Created by: Aditya Atluri
"""
from Urutu import *
import numpy as np

@Urutu("gpu")
def black_scholes(si, xi, ti, d1, d2, call_result, put_result, sqrt_ti):
	A1 = 0.31938153
	A2 = -0.356563782
	A3 = 1.781477937
	A4 = -1.821255978
	A5 = 1.330274429
	RSQRT2PI = 0.39894228040
	R = 0.02
	V = 0.3
	tid = tx + bx * Tx
	sqrt_ti[tid] = sqrt(ti[tid])
	d1[tid] = (log(si[tid]/xi[tid]) + (R + 0.5 * V * V) * ti[tid]) / (V * sqrt_ti[tid])
	d2[tid] = d1[tid] - V * sqrt_ti[tid]
	K = 1.0 / (1.0 + 0.2316419 * abs(d1[tid]))
	d1[tid] = RSQRT2PI * exp(-0.5 * d1[tid] * d1[tid]) * (K * (A1 + K * (A2 + K * (A3 + K*(A4+K*A5)))))
	K = 1.0 / (1.0 + 0.2316419 * abs(d2[tid]))
	d2[tid] = RSQRT2PI * exp(-0.5 * d2[tid] * d2[tid]) * (K * (A1 + K * (A2 + K * (A3 + K*(A4+K*A5)))))
	put_result[tid] = exp(-R * ti[tid])
	call_result[tid] = si[tid] * d1[tid] - xi[tid] * put_result[tid] * d2[tid]
	put_result[tid] = xi[tid] * put_result[tid] * (1.0 - d2[tid]) - si[tid] * (1.0 - d1[tid])
	return call_result, put_result

def rand_floats(n, min, max):
	diff = np.float32(max) - np.float32(min)
	rands = np.array(np.random.random(n), dtype=np.float32)
	rands = rands * diff
	rands = rands + np.float32(min)
	return rands

def main():
	n = 100
	S = rand_floats(n, 5, 30)
	X = rand_floats(n, 1, 100)
	T = rand_floats(n, 0.25, 10)
	sqrt_ti = np.empty_like(X)
	call_result = np.empty_like(X)
	put_result = np.empty_like(X)
	d1 = np.empty_like(X)
	d2 = np.empty_like(X)
	print black_scholes([100,1,1],[30,1,1],S, X, T, d1, d2, call_result, put_result, sqrt_ti)
#	print black_scholes(True,S, X, T, d1, d2, call_result, put_result, sqrt_ti)

if __name__ == '__main__':
	main()


# -*- coding: utf-8 -*-
"""
Created on Mon Apr 20 13:05:18 2020

@author: ToshY
"""

import numpy as np

# Activation functions
class ActivationFunctions():
    """
    Providing several activation functions used at forward and
    backward propogation in neural networks.

    Methods
    -------
    identity(x)
        Identity activation function
    identity_deriv(x)
        Derivative of Identity activation function
    sigmoid(x)
        Sigmoid activation function
    sigmoid_deriv(x)
        Derivative of Sigmoid activation function
    tanh(x)
        Tanh activation activation function
    tanh_deriv(x)
        Derivative of Tanh activation function
    arctan(x)
        Arctan activation activation function
    arctan_deriv(x)
        Derivative of Arctan activation function
    arcsin(x)
        Arcsin activation function
    arcsin_deriv(x)
        Derivative of Arcsin activation function
    elu(x, alpha=0.01)
        ELU activation function
    elu_deriv(x, alpha=0.01)
        Derivative of ELU activation function
    selu(x, alpha = 1.67326, lmbda = 1.0507)
        SELU activation function
    selu_deriv(x, alpha = 1.67326, lmbda = 1.0507)
        Derivative of SELU activation function
    relu(x)
        RELU activation function
    relu_deriv(x)
        Derivative of RELU activation function
    prelu(x, alpha=0.01)
        PRELU activation function
    prelu_deriv(x, alpha=0.01)
        Derivative of PRELU activation function
    isru(x, alpha=0.01)
        ISRU activation function
    isru_deriv(x, alpha=0.01)
        Derivative of ISRU activation function
    isrlu(x, alpha=0.01)
        ISRLU activation function
    isrlu_deriv(x, alpha=0.01)
        Derivative of ISRLU activation function
    softsign(x)
        Softsign activation function
    softsign_deriv(x)
        Derivative of Softsign activation function
    softplus(x)
        Softplus activation function
    softplus_deriv(x)
        Derivative of Softplus activation function
    softexp(x)
        Softexp activation function
    softexp_deriv(x)
        Derivative of Softexp activation function
    bent(x)
        Bent activation function
    bent_deriv(x)
        Derivative of Bent activation function
    """

    def identity(x):
        return x

    def identity_deriv(x):
        return 1

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

    def sigmoid_deriv(x):
        xs = (1/(1+np.exp(-x)))
        return (xs*(1-xs))

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

    def tanh_deriv(x):
        return (1-np.power(np.tanh(x),2))

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

    def arctan_deriv(x):
        return (1/(np.power(x,2)+1))

    def arcsin(x):
        return np.arcsin(x)

    def arcsin_deriv(x):
        return (1/np.sqrt(np.power(x,2)+1))

    def elu(x, alpha=0.01):
        x[x<=0] = (alpha*(np.exp(x[x<=0])-1))
        return x

    def elu_deriv(x, alpha=0.01):
        dx = np.ones_like(x)
        dx[x<= 0] = ((alpha*(np.exp(x[x<=0])-1))+alpha)
        return dx

    def selu(x, alpha=1.67326, lmbda=1.0507):
        x[x<0] = (alpha*(np.exp(x[x<0])-1))
        return (lmbda*x)

    def selu_deriv(x, alpha=1.67326, lmbda=1.0507):
        dx = np.ones_like(x)
        dx[x<0] = (alpha*np.exp(x[x<0]))
        return (lmbda * dx)

    def relu(x):
        x[x<0] = 0
        return x

    def relu_deriv(x):
        dx = np.ones_like(x)
        dx[x<0] = 0
        return dx

    def prelu(x, alpha=0.01):
        x[x<0] = alpha*x[x<0]
        return x

    def prelu_deriv(x, alpha=0.01):
        dx = np.ones_like(x)
        dx[x<0] = alpha
        return dx

    def isru(x, alpha=0.01):
        return (x/np.sqrt(1+alpha*np.power(x,2)))

    def isru_deriv(x, alpha=0.01):
        return np.power((1/np.sqrt(1+alpha*np.power(x,2))),3)

    def isrlu(x, alpha=0.01):
        x[x<0] = (x[x<0]/np.sqrt(1+alpha*np.power(x[x<0],2)))
        return x

    def isrlu_deriv(x, alpha=0.01):
        dx = np.ones_like(x)
        dx[x<0] = np.power((1/np.sqrt(1+alpha*np.power(x[x<0],2))),3)
        return dx

    def softsign(x):
        return (x/(1+np.abs(x)))

    def softsign_deriv(x):
        return (1/np.power((1+np.abs(x)),2))

    def softplus(x):
        return np.log(1+np.exp(x))

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

    def softexp(x, alpha=0.01):
        xt = x
        xt[alpha<0] = ((-np.log(1-alpha*(x[alpha<0]+alpha)))/alpha)
        xt[alpha>0] = (((np.exp(alpha*x[alpha>0])-1)/alpha)+alpha)
        return xt

    def softexp_deriv(x, alpha=0.01):
        dx=x
        dx[alpha<0] = (1/(1-alpha*(alpha+x[alpha<0])))
        dx[alpha>=0] = np.exp(alpha*x[alpha>=0])
        return dx

    def bent(x):
        return (((np.sqrt(np.power(x,2)+1)-1)/2)+x)

    def bent_deriv(x):
        return ((x/(2*np.sqrt(np.power(x,2)+1)))+1)


import numpy as np
import opytimizer.math.benchmark as b

# Creating an input vector
x = np.array([0.5, 0.5, 1, 1])
print(f'x: {x}')

# Calculating Sphere's function
y = b.sphere(x)
print(f'Sphere f(x): {y}')

# Calculating Exponential's function
y = b.exponential(x)
print(f'Exponential f(x): {y}')


import numpy as np
from numpy import *
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation

class AmplitudeModulation():
	def __init__(self, Ac, Am, fc, fm):
		'''
		parameters:
		=================
		Ac: Amplitude of carrier signal
		Am: Amplitude of message signal
		fc: frequency of carrier signal
		fm: freaquency of message signal

		'''
		self.Ac= Ac
		self.Am= Am
		self.fc= fc
		self.fm= fm
		self.t= np.arange(0, 2*pi, 0.01)

	def createSignals(self):
		'''
		creates 'carrier', 'message' and 'modulated' signals

		c= Ac.sin(2.π.fc.t)
		m= Am.sin(2.π.fm.t)
		am= (Ac+Am.sin(2.π.fm.t)).sin(2.π.fc.t)

		'''
		#carrier signal
		c= lambda t: self.Ac*sin(2*pi*self.fc*t)

		#message signal
		m= lambda t: self.Am*sin(2*pi*self.fm*t)

		#modulated signal
		am= lambda t: (self.Ac+m(t))*sin(2*pi*self.fc*t)

		return c, m, am

	def plot(self, c, m, am, labels, *args):
		'''
		parameters
		===================
		c: carrier signal
		m: message signal
		am: modulated signal
		labels: dictionary of labels for the graph
		'''

		if len(args)==1:
			fig, (ax1, ax2, ax3, ax4)= plt.subplots(4,1)
			ax= (ax1, ax2, ax3, ax4)
		else:
			fig, (ax1, ax2, ax3)= plt.subplots(3,1)
			ax= (ax1, ax2, ax3)

		fig.suptitle(labels['title'])

		for each in ax:
			each.set_ylabel(labels['ylabel'])
			each.set_xlabel(labels['xlabel'])
			each.axhline()

		ax1.set_title(labels['subtitle1'])
		ax2.set_title(labels['subtitle2'])
		ax3.set_title(labels['subtitle3'])

		line1, =ax1.plot(self.t, c(self.t))
		line2, =ax2.plot(self.t, m(self.t))
		line3, =ax3.plot(self.t, am(self.t), color='r')

		anim1= FuncAnimation(fig, self.animate, fargs= (c, line1), init_func= None, interval=2, blit=True, save_count=50 )
		anim2= FuncAnimation(fig, self.animate, fargs= (m, line2), init_func= None, interval=2, blit=True, save_count=50 )
		anim3= FuncAnimation(fig, self.animate, fargs= (am, line3), init_func= None, interval=2, blit=True, save_count=50 )

		if len(args)==1:
			ax4.set_title(labels['subtitle4'])
			line4, =ax4.plot(self.t, args[0](self.t), color='r')
			#anim3=''
			anim4= FuncAnimation(fig, self.animate, fargs= (am, line4), init_func= None, interval=2, blit=True, save_count=50 )

		plt.tight_layout()
		plt.show()

	def animate(self, i, *fargs):
		func= fargs[0]
		line= fargs[1]
		line.set_ydata(func(self.t+i/40))
		return line,

if __name__=='__main__':

	labels= {
	'title': '====Amplitude Modulation====',
	'xlabel': 'Time(Sec)',
	'ylabel': 'Amplitude',
	'subtitle1': 'Carrier Signal: Ac.sin(Wc*t)',
	'subtitle2': 'Message Signal: Am.sin(Wm*t)',
	'subtitle3': 'Amplitude Modulated Signal: [Ac+m(t)]sin(Wc.t)',
	'subtitle4': 'optional'
	}

	am= AmplitudeModulation(Ac= 3, Am= 2, fc= 5, fm= 1)
	am.plot(*am.createSignals(), labels)


import pandas as pd
import numpy as np
import statsmodels.api as sm
import matplotlib.pyplot as plt
from statsmodels.tsa.arima_model import ARIMA

# Let's build a time series of diapers
vals = [9, 12, 8, 15, 10, 17, 15, 13, 10, 15, 13, 11, 14, 12, 13, 12, 7, 14, 10, 12, 11]
dti = pd.date_range('2020-05-05', periods=len(vals), freq='D')

# Generate the time series:
diapers = pd.Series(vals, index=dti)

# Let's look at the data
plt.plot(diapers)
plt.show()

# Let's forecast diaper needs for the next month.
# Lifting code and modifying from this blog post code quickly:
# https://kanoki.org/2020/04/30/time-series-analysis-and-forecasting-with-arima-python/

# Let's look at a decomposition
decomposition = sm.tsa.seasonal_decompose(diapers, model='additive')
plt.rcParams["figure.figsize"] = [16,9]
fig = decomposition.plot()
fig.show()
junk = input("Press any key to continue")
plt.close()

# Let's fit an ARIMA(1,1). Later can do selection; for first pass use 1,1 and 1 lag diff
mod = ARIMA(diapers,order=(1,1,1)) # order: (AR, diff, MA)
results = mod.fit()
print(results.summary())

# Brass tacks: quickly forecast
T = 30
forecast,err,ci = results.forecast(steps=T, alpha=0.05)
df_forecast = pd.DataFrame({'forecast':forecast},index=pd.date_range(start='5/26/2020', periods=T, freq='D'))

# Plot the forecast and time series -- "does this look reasonable?"
ax = diapers.plot(label='observed', figsize=(20, 15))
df_forecast.plot(ax=ax,label='Forecast',color='r')
ax.fill_between(df_forecast.index,
                ci[:,0],
                ci[:,1], color='b', alpha=.25)
ax.set_xlabel('Days')
ax.set_ylabel('Diapers')
plt.legend()
plt.show()

# Of course what we are about is the number of diapers needed over the next month.
print('forcast of next 30 days: ', np.round(forecast))
print('sum(forecast) for next 30 days:', sum(np.round(forecast)))

import numpy,import statsmodels,from statsmodels


import numpy as np

from . import Operation, Tensor

class CrossEntropy(Operation):
    """
    the cross entropy cost function
    """

    def __call__(self, h, y, eps):
        """
        given the hypothesis and the correct
        outputs, calculate the log loss between
        h and y assuming one-hot encoded

        :type h: np.ndarray
        :desc h: predicted classes [m x k]

        :type y: np.ndarray
        :desc y: actual classes [m x k]

        :type eps: float
        :desc eps: make all values in h between (eps, 1-eps)
                   so we dont get any divide by 0 errors
        """
        self.__previous = getattr(h, 'previous', None)

        h = np.clip(h, eps, 1 - eps)
        self.__input = y, h

        cost = y * np.log(h) + (1 - y) * np.log(1 - h)
        operation = self if self.__previous else None
        return Tensor(-np.mean(cost), operation)

    def backprop(self, sigma, optim):
        """
        the cross entropy function is:
            y * np.log(h) + (1 - y) * np.log(1 - h)

        after some math, the derivative
        with respect to h is:
            (1 - y) / (1 - h) - y / h

        and we multiply this by the backpropagated error
        """
        if self.__previous:
            y, h = self.__input
            change = (1 - y) / (1 - h) - y / h
            next_sigma = change * sigma
            self.__previous.backprop(next_sigma, optim)

def cross_entropy(h, y, eps=1e-9):
    """
    a helper function for creating a
    cross entropy cost so that it
    looks nicer when we call it later
    """
    return CrossEntropy()(h, y, eps)


from numpy import sqrt, sum, dot, square, shape, mean, array
from numpy.linalg.linalg import svd
from numpy.linalg import inv

def procrustes(m1, m2):

    # centralize matrices
    mean_m1 = [mean(column) for column in m1.T]
    m1 = m1-mean_m1
    mean_m2 = [mean(column) for column in m2.T]
    m2 = m2-mean_m2

    # scaling
    scale_m1 = sqrt(sum(square(m1))/(m1.shape[1]))
    scale_m2 = sqrt(sum(square(m2))/(m2.shape[1]))
    m2 = (m2/scale_m2)*scale_m1

    # rotation
    u, s, v = svd(dot(m1.T, m2))
    r = dot(v.T, u.T)
    m2 = dot(m2, r)

    # set m2 center to m1 center
    m2 = m2+mean_m1

    return m2

def procrustes_distance(m1, m2):
    distance = sum(square(m1 - m2))

    return distance

def scale_width(m, width):
    # scale width model m to width

    # get width of model
    min_x_mean = min(m[:,0])
    max_x_mean = max(m[:,0])
    meanwidth = max_x_mean-min_x_mean

    # center model
    mean_m = [mean(column) for column in m.T]
    m -= mean_m

    # scale model
    m = (m/meanwidth)*width

    # uncenter model
    m += mean_m

    return m

def get_reverse_transforms(mat1, mat2):
    # get the reverse procrustes transformation to align m2 with m1

    m1 = array(mat1)
    m2 = array(mat2)

    # centralize matrices
    mean_m1 = [mean(column) for column in m1.T]
    m1 = m1-mean_m1
    mean_m2 = [mean(column) for column in m2.T]
    m2 = m2-mean_m2

    t = array(mean_m2)-array(mean_m1)

    # scaling
    scale_m1 = sqrt(sum(square(m1))/(m1.shape[1]))
    scale_m2 = sqrt(sum(square(m2))/(m2.shape[1]))
    m2 = (m2/scale_m2)*scale_m1

    sc = scale_m2/scale_m1

    # rotation
    u, s, v = svd(dot(m1.T, m2))
    r = inv(dot(v.T, u.T))

    return sc, r, mean_m1, mean_m2

def transform(mat, s, r, mean1, mean2):
    # transform matrix via transform t, scale s, rotation r

    m = array(mat)

    mean_m = [mean(column) for column in m.T]
    m -= mean_m
    # TODO : which mean should I subtract here?
    #m -= mean1
    m = dot(m, r)
    m *= s
    #m += t
    #m += mean_m
    m += mean2
    return m


import math
import numpy as np
import scipy as sp
import matplotlib.pyplot as plt
import matplotlib.mlab as mlab
from scipy.stats import chi2

data = np.loadtxt('data/whData.dat',dtype=np.object,comments='#',delimiter=None)

# read height and weight data into into a 2d matrix
data = data[:,0:2].astype(np.float)

# remove the outliers: training data= traind
trainD = data[data[:,0] >= 0]

# prediction data (outliers): Prediction Data= predD
predD = data[data[:,0] ==-1]

# create height vector for prediction data: PreX,PreY for predictionX and Prediction Y
preX = np.copy(predD[:,1])

# weight vector for train data
y = np.copy(trainD[:,0])
# create height vector for train data
x = np.copy(trainD[:,1])
#calculation!
mw = np.round(np.mean(y),2)
mh = np.round(np.mean(x),2)
devw = np.round(np.std(y),2)
devh = np.round(np.std(x),2)
corrcoef = np.corrcoef(x,y)[0,1]
#
#
z = 0
preY =np.zeros([len(preX)])
while (z!=len(preX)):
    h0 = preX[z]
    prediction = mw+corrcoef *(h0 - mh) *devw/devh
    print(h0)
    print (prediction)
    preY[z] = prediction
    z= z + 1
#plotting

plt.plot(x, y, 'go',preX,preY,'rs')
plt.axis([np.amin(x)-10, np.amax(x)+20, np.amin(y)-10, np.amax(y)+20])
plt.savefig("out/task22/conditional_expectation.png", bbox_inches="tight", pad_inches=0)
plt.show()


from math import factorial, pow, e, fabs, pi, sqrt
from probability import combination
import scipy.integrate as integrate
from functools import reduce

# Define binomial se usa cuando se tiene un tamano de muestra una probabilidad de exito y valor a encontrar probabilidad
# Por ejemplo probabilidad que de 30 personas(length) 8 (number_succes) con un porcentaje de exito del 0.5 (succes probability)
def binomial_distribution(length, succes_probability, number_succes):
  div = factorial(length) / (factorial(number_succes) * factorial(length - number_succes))
  multiply = pow(succes_probability, number_succes) * pow(1 - succes_probability, length - number_succes)

  return  div * multiply

# Se toma cuando en la distrubucion binomial se pide encontrar la probabilidad de algun rango, por ejemplo x < 3
# se pone [0,1,2,3]
def acumulated_binomial(cases, length, succes_probability):
  cases_binomial = map(lambda x: binomial_distribution(length, succes_probability, float(x)), cases)
  probability = reduce(lambda a,b: a + b, cases_binomial)

  return probability

def hypergeometric(length, sample_especial, sample_length, x):
  first = float(combination(sample_especial, x))
  second = float(combination(length - sample_especial, sample_length - x))
  third = float(combination(length, sample_length))

  return first * second / third

def acumulated_hypergeometric(length, sample_especial, sample_length, cases):
  cases_hypergeometric = map(lambda x: hypergeometric(length, sample_especial, sample_length, x), cases)
  probability = reduce(lambda a,b: a + b, cases_hypergeometric)
  return probability

def poisson(x, average):
  return (pow(average, x) * pow(e, -average)) / factorial(x)

def exponential(gap, average):
  return 1 - pow(e, -average * gap)

def uniform(x1, x2, greather, less):
  return fabs((x2 - x1) / (greather - less))

def norm(deviation, average, x1, x2):
  inte = integrate.quad(lambda x : pow(e,-0.5 * (pow(x - average, 2) / pow(deviation, 2)) ), x1, x2)
  result = inte[0]
  constant = 1 / (sqrt(2 * pi) * deviation)

  return constant * result

def get_z(x_, average, deviation, n):
    return (x_ - average) / (deviation / sqrt(n))

def when_get_x(average, deviation, percent):
  from scipy.stats import norm
  return norm(average, deviation).ppf(percent)


import numpy as np

class Loss():
    def __init__(self):
        return

    def forward(self, y_pred, y_true):
        pass

    def backward(self, y_pred, y_true):
        pass

class MSE(Loss):
    def __init__(self):
        super().__init__()
        return

    def forward(self, y_pred, y_true):
        assert y_pred.shape == y_true.shape
        return np.mean((y_true - y_pred)**2)

    def backward(self, y_pred, y_true):
        return y_pred - y_true

class CE(Loss):
    def __init__(self):
        super().__init__()
        return

    def forward(self, y_pred, y_true):
        assert y_pred.shape == y_true.shape
        return -np.mean(y_true*np.log(y_pred) + (1-y_true)*np.log(1-y_pred))

    def backward(self, y_pred, y_true):
        return (y_pred - y_true) / (y_pred * (1- y_pred))


import numpy as np

# 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)
   return np.divide (expL, expL.sum())

def cross_entropy(Y, P):
    Y = np.float_(Y)
    P = np.float_(P)
    return -np.sum(Y * np.log(P) + (1 - Y) * np.log(1 - P))


import numpy as np

# Метод параболической аппроксимации Пауэлла
def powell(func, a: float, b: float, eps =0.01):
    # step 1
    x1 = a
    x2 = (a + b) / 2
    x3 = b

    X = [x1, x2, x3]
    # step 2
    while (True):
        min_x = X[0]
        for i in X:
            if (func(i)<func(min_x)):
                min_x = i

        # step 3
        num = (X[1] ** 2 - X[2] ** 2) * func(X[0]) + (X[2] ** 2 - X[0] ** 2) * func(X[1]) + (X[0] ** 2 - X[1] ** 2)* func(X[2])
        denum = (X[1] - X[2]) * func(X[0]) + (X[2] - X[0]) * func(X[1]) + (X[0] - X[1]) * func(X[2])
        X.append(0.5 * (num / denum))
        # step 4
        if(abs(X[3] - min_x) <= eps):
            break
        #step 5
        X.sort()

        #step 6
        max_x = 0
        for i in range(4):
            if (func(X[i])>func(X[max_x])):
                max_x = i
        X.pop(max_x)

 #step 7
    return X[-1]


import numpy as np
np.random.seed(10)

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

class LogisticsReg():
    def __init__(self,learn_rate=1e-3,niter=100000):
        self.lr=learn_rate
        self.iter=int(niter)

    def fit(self,x,y):
        x=np.insert(x, 0, values=1, axis=1)
        w=np.random.uniform(size=(x.shape[1]))

        for i in range(self.iter):
            p = sigmoid(x.dot(w))
            w -= self.lr * x.T.dot(p - y)

        self.w=w

    def predict(self,x):
        x=np.insert(x, 0, values=1, axis=1)
        return sigmoid(x.dot(self.w))

if __name__=='__main__':
    data=np.loadtxt('data.csv',delimiter=',',skiprows=1)
    np.random.shuffle(data)

    x=data[:600,:-1]
    y=data[:600,-1]

    mean=np.mean(x,axis=0)
    std=np.std(x,axis=0)
    x=(x-mean)/std

    x_val=data[600:,:-1]
    y_val=data[600:,-1]
    x_val=(x_val-mean)/std

    model=LogisticsReg()
    model.fit(x,y)

    import sklearn.metrics
    pred=model.predict(x_val)
    print(sklearn.metrics.roc_auc_score(y_val,pred))
    '''
    with open('acc_thres.csv','w') as f:
        for i in range(100):
            pred=model.predict(x_val)>(i/100)
            acc=sklearn.metrics.accuracy_score(y_val,pred)
            f.write('%s,%s\n'%(i/100,acc))
    '''
    with open('acc_lr.csv','w') as f:
        for i in range(-10,1):
            model=LogisticsReg(10**i)
            model.fit(x,y)
            pred=model.predict(x_val)>0.5
            acc=sklearn.metrics.accuracy_score(y_val,pred)
            f.write('%s,%s\n'%(10**i,acc))


import numpy as np

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

def d_sigmoid(_x_set):
    return (1 - sigmoid(_x_set)) * sigmoid(_x_set)

def softmax(_x_set):
    x_row_max = _x_set.max(axis=-1)
    x_row_max = x_row_max.reshape(list(_x_set.shape)[:-1] + [1])
    _x_set = _x_set - x_row_max
    x_exp = np.exp(_x_set)
    x_exp_row_sum = x_exp.sum(axis=-1).reshape(list(_x_set.shape)[:-1] + [1])
    return x_exp / x_exp_row_sum

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

def d_relu(_x_set):
    _x_set[_x_set <= 0] = 0
    _x_set[_x_set > 0] = 1
    return _x_set

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

def d_tanh(_x_set):
    return 1 - np.tanh(_x_set) ** 2

def activation_function(method, x):
    if method == 'relu':
        _a = relu(x)
    elif method == 'sigmoid':
        _a = sigmoid(x)
    elif method == 'softmax':
        _a = softmax(x)
    elif method is None:
        _a = x
    else:
        _a = []
        print("No such activation: {}!".format(method))
        exit(1)
    return _a

def derivative_function(method, x):
    if method == 'relu':
        _d = d_relu(x)
    elif method == 'sigmoid':
        _d = d_sigmoid(x)
    elif method is None:
        _d = 1
    else:
        _d = []
        print("No such activation: {}!".format(method))
        exit(1)
    return _d


# -*- coding: utf-8 -*-
"""
Created on Tue Mar  1 16:53:49 2022

@author: Luminous Isaac
"""
######################## Linear Programming Plt #############################
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
#from pylab import figure, text, scatter, show

# Construct lines
x = np.linspace(0.0,50,100)
y1 = 3.0*x - 33
y2 = (-1/15)*x + 15
y3 = (14/5)*x - 28

# Make plot
plt.plot(x, y1, label=r'$y1 = 3.0*x - 33$')
plt.plot(x, y2, label=r'$y2 = (-1/15)*x + 15$')
plt.plot(x, y3, label=r'$y3 = (14/5)*x - 28$')

plt.xlim((0.0, 50.000))
plt.ylim((0.0, 50.000))
plt.xlabel(r'$x$')
plt.ylabel(r'$y$')

# Fill feasible region
y5 = np.minimum(y1, y3)
#y6 = np.maximum(y1, y3)
plt.fill_between(x, y5, y2, where=y5>y2, color='grey', alpha=0.5)

plt.grid(True, linestyle='-.')
plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)

#plt.savefig('ordering_constraints.eps',dpi=600,bbox_inches='tight')
plt.show()

######################## Hadley-Whitin Algorithm ############################
from sympy import *
import math

def expectation():
    x = Symbol('x')
    Ex = integrate(x*1/32, (x, 0, 32)) ##change
    return Ex

def HWA(D, K, h, p, n):
    y_hat = math.sqrt((2 * D * (K + p * expectation())) / h)
    y_wave = (p * D) / h
    if y_wave < y_hat:
        return "Hadley-Whitin method will not converge."
    else:
        y = math.sqrt(2 * D * K / h)
        R = 32*(1 - y * h / (p * D)) ## change
        if n == 1:
            return y, R
        else:
            for i in range(2, n+1):
                x = Symbol('x')
                S_R = integrate((x - R) / 32, (x, R, 32)) ##change
                y = math.sqrt((2 * D * (K + p * S_R)) / h)
                R = 32*(1 - y * h / (p * D)) ## change
    return y_hat, y_wave, y, R

HWA(30, 4, 0.48, 1.11, 3)


#Importing Dependencies

import math
import numpy as np
import h5py
import matplotlib.pyplot as plt
import tensorflow as tf
from tensorflow.python.framework import ops
from tf_utils import load_dataset, random_mini_batches, convert_to_one_hot, predict

%matplotlib inline
np.random.seed(1)

#Computing the following loss using tensorflow
#Loss(y_hat, y) = np.power((y_hat - y),2)

y_hat = tf.constant(36, name='y_hat')            # Define y_hat constant. Set to 36.
y = tf.constant(39, name='y')                    # Define y. Set to 39

loss = tf.Variable((y - y_hat)**2, name='loss')  # Create a variable for the loss

init = tf.global_variables_initializer()         # When init is run later (session.run(init)),
                                                 # the loss variable will be initialized and ready to be computed
with tf.Session() as session:                    # Create a session and print the output
    session.run(init)                            # Initializes the variables
    print(session.run(loss))                     # Prints the loss

#Output = 9

a = tf.constant(2)
b = tf.constant(10)
c = tf.multiply(a,b)
print(c)

#Output
#Tensor("Mul:0", shape=(), dtype=int32)

print(sess.run(c))

#Output = 20

x = tf.placeholder(tf.int64, name = 'x')
print(sess.run(2 * x, feed_dict = {x: 3}))
sess.close()

#Ouptut = 6

#X = tf.constant(np.random.randn(3,1), name = "X")

#You might find the following functions helpful:

#    tf.matmul(..., ...) to do a matrix multiplication
#    tf.add(..., ...) to do an addition
#    np.random.randn(...) to initialize randomly

def linear_function():
    """
    Implements a linear function:
            Initializes W to be a random tensor of shape (4,3)
            Initializes X to be a random tensor of shape (3,1)
            Initializes b to be a random tensor of shape (4,1)
    Returns:
    result -- runs the session for Y = WX + b
    """

    np.random.seed(1)

    X = tf.constant(np.random.randn(3, 1), name = 'x')
    W = tf.constant(np.random.randn(4, 3), name = 'W')
    b = tf.constant(np.random.randn(4, 1), name = 'b')
    Y = tf.add(tf.matmul(W, X), b

    sess = tf.Session()
    result = sess.run(Y)

    # close the session
    sess.close()

    return result

print( "result = " + str(linear_function()))

#Output := result 	[[-2.15657382] [ 2.95891446] [-1.08926781] [-0.84538042]]

#Note that there are two typical ways to create and use sessions in tensorflow:

#Method 1:

#sess = tf.Session()
# Run the variables initialization (if needed), run the operations
#result = sess.run(..., feed_dict = {...})
#sess.close() # Close the session

#Method 2:

#with tf.Session() as sess:
    # run the variables initialization (if needed), run the operations
    # result = sess.run(..., feed_dict = {...})
    # This takes care of closing the session for you :)

def sigmoid(z):
    """
    Computes the sigmoid of z

    Arguments:
    z -- input value, scalar or vector

    Returns:
    results -- the sigmoid of z
    """

    # Create a placeholder for x. Name it 'x'.
    x = tf.placeholder(tf.float32, name = 'x')

    # compute sigmoid(x)
    sigmoid = tf.sigmoid(x)

    with tf.Session() as sess:
        # Run session and call the output "result"
        result = sess.run(sigmoid, feed_dict = {x : z})

    return result
print ("sigmoid(0) = " + str(sigmoid(0)))
print ("sigmoid(12) = " + str(sigmoid(12)))

#Output
sigmoid(0) = 0.5
sigmoid(12) = 0.999994

#1.3 - Computing the Cost

def cost(logits, labels):
    """
    Computes the cost using the sigmoid cross entropy

    Arguments:
    logits -- vector containing z, output of the last linear unit (before the final sigmoid activation)
    labels -- vector of labels y (1 or 0)

    Note: What we've been calling "z" and "y" in this class are respectively called "logits" and "labels"
    in the TensorFlow documentation. So logits will feed into z, and labels into y.

    Returns:
    cost -- runs the session of the cost (formula (2))
    """

    # Creating the placeholders for "logits" (z) and "labels" (y)
    z = tf.placeholder(tf.float32, name = 'z')
    y = tf.placeholder(tf.float32,   name = 'x')

    # Using the loss function
    cost = tf.nn.sigmoid_cross_entropy_with_logits(logits = z, labels = y)

    # Creating a session
    sess = tf.Session()

    # Running the session
    cost = sess.run(cost, feed_dict = {z : logits, y : labels})

    # Closing the session (approx. 1 line). See method 1 above.
    sess.close()

    return cost

logits = sigmoid(np.array([0.2,0.4,0.7,0.9]))
cost = cost(logits, np.array([0,0,1,1]))
print ("cost = " + str(cost))

#Output
cost 	 = [ 1.00538719 1.03664088 0.41385433 0.39956614]

#1.4 - Using One Hot encodings

#Many times in deep learning you will have a y vector with numbers ranging from 0 to C-1, where C is the
#number of classes. If C is for example 4, then you might have the following y vector which you will need to convert as follows:

#This is called a "one hot" encoding, because in the converted representation exactly one element of each column is
#"hot" (meaning set to 1). To do this conversion in numpy, you might have to write a few lines of code.
#In tensorflow, you can use one line of code:

    #tf.one_hot(labels, depth, axis)

def one_hot_matrix(labels, C):
    """
    Creates a matrix where the i-th row corresponds to the ith class number and the jth column
                     corresponds to the jth training example. So if example j had a label i. Then entry (i,j)
                     will be 1.

    Arguments:
    labels -- vector containing the labels
    C -- number of classes, the depth of the one hot dimension

    Returns:
    one_hot -- one hot matrix
    """

    # Creating a tf.constant equal to C (depth), name it 'C'. (approx. 1 line)
    C = tf.constant(C, tf.int32, name = 'C')

    # Using tf.one_hot, be careful with the axis
    one_hot_matrix = tf.one_hot(labels,C, axis = 0)

    # Creating the session
    sess = tf.Session()

    # Running the session
    one_hot = sess.run(one_hot_matrix)

    # Closing the session (approx. 1 line). See method 1 above.
    sess.close()

    return one_hot

labels = np.array([1,2,3,2,1])
one_hot = one_hot_matrix(labels, C = 3)
print ("one_hot = " + str(one_hot))

#Output
one_hot = [[ 0.  0.  0.  0.  0.]
 [ 1.  0.  0.  0.  1.]
 [ 0.  1.  0.  1.  0.]]

 #1.5 - Initialize with zeros and ones
def ones(shape):
    """
    Creates an array of ones of dimension shape

    Arguments:
    shape -- shape of the array you want to create

    Returns:
    ones -- array containing only ones
    """

    # Creating "ones" tensor using tf.ones(...).
    ones = tf.ones(shape)

    # Creating the session
    sess = tf.Session()

    # Running the session to compute 'ones'
    ones = sess.run(ones)

    # Closing the session
    sess.close()

    return ones

print ("ones = " + str(ones([3])))

#Output
ones = [ 1.  1.  1.]

#2 - Building your first neural network in tensorflow

 #   Training set: 1080 pictures (64 by 64 pixels) of signs representing numbers from 0 to 5 (180 pictures per number).
 #   Test set: 120 pictures (64 by 64 pixels) of signs representing numbers from 0 to 5 (20 pictures per number).

#Note that this is a subset of the SIGNS dataset. The complete dataset contains many more signs.

#Here are examples for each number, and how an explanation of how we represent the labels. These are the original
#pictures, before we lowered the image resolutoion to 64 by 64 pixels.

# Loading the dataset
X_train_orig, Y_train_orig, X_test_orig, Y_test_orig, classes = load_dataset()

#Change the index below and run the cell to visualize some examples in the dataset.

# Example of a picture
index = 0
plt.imshow(X_train_orig[index])
print ("y = " + str(np.squeeze(Y_train_orig[:, index])))

#Output y = 5

#As usual you flatten the image dataset, then normalize it by dividing by 255. On top of that, you will convert each label to a
#one-hot vector as shown in Figure 1. Run the cell below to do so.

# Flatten the training and test images
X_train_flatten = X_train_orig.reshape(X_train_orig.shape[0], -1).T
X_test_flatten = X_test_orig.reshape(X_test_orig.shape[0], -1).T
# Normalize image vectors
X_train = X_train_flatten/255.
X_test = X_test_flatten/255.
# Convert training and test labels to one hot matrices
Y_train = convert_to_one_hot(Y_train_orig, 6)
Y_test = convert_to_one_hot(Y_test_orig, 6)

print ("number of training examples = " + str(X_train.shape[1]))
print ("number of test examples = " + str(X_test.shape[1]))
print ("X_train shape: " + str(X_train.shape))
print ("Y_train shape: " + str(Y_train.shape))
print ("X_test shape: " + str(X_test.shape))
print ("Y_test shape: " + str(Y_test.shape))

#Output
number of training examples = 1080
number of test examples = 120
X_train shape: (12288, 1080)
Y_train shape: (6, 1080)
X_test shape: (12288, 120)
Y_test shape: (6, 120)

#Note that 12288 comes from 64×64×364×64×3. Each image is square, 64 by 64 pixels, and 3 is for
#the RGB colors. Please make sure all these shapes make sense to you before continuing.

#The model is LINEAR -> RELU -> LINEAR -> RELU -> LINEAR -> SOFTMAX. The SIGMOID output layer has been
#converted to a SOFTMAX. A SOFTMAX layer generalizes SIGMOID to when there are more than two classes.

#2.1 - Create placeholders

#Your first task is to create placeholders for X and Y. This will allow you to later pass your training
#data in when you run your session.

def create_placeholders(n_x, n_y):
    """
    Creates the placeholders for the tensorflow session.

    Arguments:
    n_x -- scalar, size of an image vector (num_px * num_px = 64 * 64 * 3 = 12288)
    n_y -- scalar, number of classes (from 0 to 5, so -> 6)

    Returns:
    X -- placeholder for the data input, of shape [n_x, None] and dtype "float"
    Y -- placeholder for the input labels, of shape [n_y, None] and dtype "float"

    Tips:
    - You will use None because it let's us be flexible on the number of examples you will for the placeholders.
      In fact, the number of examples during test/train is different.
    """

    X = tf.placeholder(tf.float32,[n_x,None],name = "X")
    Y = tf.placeholder(tf.float32,[n_y,None],name = "Y")

    return X, Y

X, Y = create_placeholders(12288, 6)
print ("X = " + str(X))
print ("Y = " + str(Y))

#Output
X = Tensor("X:0", shape=(12288, ?), dtype=float32)
Y = Tensor("Y:0", shape=(6, ?), dtype=float32)

#2.2 - Initializing the parameters
#W1 = tf.get_variable("W1", [25,12288], initializer = tf.contrib.layers.xavier_initializer(seed = 1))
#b1 = tf.get_variable("b1", [25,1], initializer = tf.zeros_initializer())

def initialize_parameters():
    """
    Initializes parameters to build a neural network with tensorflow. The shapes are:
                        W1 : [25, 12288]
                        b1 : [25, 1]
                        W2 : [12, 25]
                        b2 : [12, 1]
                        W3 : [6, 12]
                        b3 : [6, 1]

    Returns:
    parameters -- a dictionary of tensors containing W1, b1, W2, b2, W3, b3
    """

    tf.set_random_seed(1)                   # so that your "random" numbers match ours

    W1 = tf.get_variable("W1",[25,12288],initializer=tf.contrib.layers.xavier_initializer(seed = 1))
    b1 = tf.get_variable("b1",[25,1], initializer = tf.zeros_initializer())
    W2 = tf.get_variable("W2",[12,25],initializer=tf.contrib.layers.xavier_initializer(seed = 1))
    b2 = tf.get_variable("b2",[12,1], initializer = tf.zeros_initializer())
    W3 = tf.get_variable("W3",[6,12],initializer=tf.contrib.layers.xavier_initializer(seed = 1))
    b3 = tf.get_variable("b3",[6,1], initializer = tf.zeros_initializer())

    parameters = {"W1": W1,
                  "b1": b1,
                  "W2": W2,
                  "b2": b2,
                  "W3": W3,
                  "b3": b3}

    return parameters

  tf.reset_default_graph()
with tf.Session() as sess:
    parameters = initialize_parameters()
    print("W1 = " + str(parameters["W1"]))
    print("b1 = " + str(parameters["b1"]))
    print("W2 = " + str(parameters["W2"]))
    print("b2 = " + str(parameters["b2"]))

#Output
W1 = <tf.Variable 'W1:0' shape=(25, 12288) dtype=float32_ref>
b1 = <tf.Variable 'b1:0' shape=(25, 1) dtype=float32_ref>
W2 = <tf.Variable 'W2:0' shape=(12, 25) dtype=float32_ref>
b2 = <tf.Variable 'b2:0' shape=(12, 1) dtype=float32_ref>
#As expected, the parameters haven't been evaluated yet.

#2.3 - Forward propagation in tensorflow

 #   tf.add(...,...) to do an addition
 #   tf.matmul(...,...) to do a matrix multiplication
 #   tf.nn.relu(...) to apply the ReLU activation

def forward_propagation(X, parameters):
    """
    Implements the forward propagation for the model: LINEAR -> RELU -> LINEAR -> RELU -> LINEAR -> SOFTMAX

    Arguments:
    X -- input dataset placeholder, of shape (input size, number of examples)
    parameters -- python dictionary containing your parameters "W1", "b1", "W2", "b2", "W3", "b3"
                  the shapes are given in initialize_parameters

    Returns:
    Z3 -- the output of the last LINEAR unit
    """

    # Retrieve the parameters from the dictionary "parameters"
    W1 = parameters['W1']
    b1 = parameters['b1']
    W2 = parameters['W2']
    b2 = parameters['b2']
    W3 = parameters['W3']
    b3 = parameters['b3']

                                                                        # Numpy Equivalents:
    Z1 = tf.add(tf.matmul(W1,X),b1)                                     # Z1 = np.dot(W1, X) + b1
    A1 = tf.nn.relu(Z1)                                                 # A1 = relu(Z1)
    Z2 = tf.add(tf.matmul(W2,A1),b2)                                    # Z2 = np.dot(W2, a1) + b2
    A2 = tf.nn.relu(Z2)                                                 # A2 = relu(Z2)
    Z3 = tf.add(tf.matmul(W3,A2),b3)                                    # Z3 = np.dot(W3,Z2) + b3

    return Z3

tf.reset_default_graph()

with tf.Session() as sess:
    X, Y = create_placeholders(12288, 6)
    parameters = initialize_parameters()
    Z3 = forward_propagation(X, parameters)
    print("Z3 = " + str(Z3))

#Output
Z3 = Tensor("Add_2:0", shape=(6, ?), dtype=float32)

#2.4 Compute cost
 def compute_cost(Z3, Y):
    """
    Computes the cost

    Arguments:
    Z3 -- output of forward propagation (output of the last LINEAR unit), of shape (6, number of examples)
    Y -- "true" labels vector placeholder, same shape as Z3

    Returns:
    cost - Tensor of the cost function
    """

    # to fit the tensorflow requirement for tf.nn.softmax_cross_entropy_with_logits(...,...)
    logits = tf.transpose(Z3)
    labels = tf.transpose(Y)

    cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits = logits, labels = labels))

    return cost

tf.reset_default_graph()

with tf.Session() as sess:
    X, Y = create_placeholders(12288, 6)
    parameters = initialize_parameters()
    Z3 = forward_propagation(X, parameters)
    cost = compute_cost(Z3, Y)
    print("cost = " + str(cost))

 #Output
 cost = Tensor("Mean:0", shape=(), dtype=float32)

#2.5 - Backward propagation & parameter updates
def model(X_train, Y_train, X_test, Y_test, learning_rate = 0.0001,
          num_epochs = 1500, minibatch_size = 32, print_cost = True):
    """
    Implements a three-layer tensorflow neural network: LINEAR->RELU->LINEAR->RELU->LINEAR->SOFTMAX.

    Arguments:
    X_train -- training set, of shape (input size = 12288, number of training examples = 1080)
    Y_train -- test set, of shape (output size = 6, number of training examples = 1080)
    X_test -- training set, of shape (input size = 12288, number of training examples = 120)
    Y_test -- test set, of shape (output size = 6, number of test examples = 120)
    learning_rate -- learning rate of the optimization
    num_epochs -- number of epochs of the optimization loop
    minibatch_size -- size of a minibatch
    print_cost -- True to print the cost every 100 epochs

    Returns:
    parameters -- parameters learnt by the model. They can then be used to predict.
    """

    ops.reset_default_graph()                         # to be able to rerun the model without overwriting tf variables
    tf.set_random_seed(1)                             # to keep consistent results
    seed = 3                                          # to keep consistent results
    (n_x, m) = X_train.shape                          # (n_x: input size, m : number of examples in the train set)
    n_y = Y_train.shape[0]                            # n_y : output size
    costs = []                                        # To keep track of the cost

    # Create Placeholders of shape (n_x, n_y)

    X, Y = create_placeholders(n_x, n_y)

    # Initialize parameters

    parameters = initialize_parameters()

    # Forward propagation: Build the forward propagation in the tensorflow graph

    Z3 = forward_propagation(X, parameters)

    # Cost function: Add cost function to tensorflow graph

    cost = compute_cost(Z3, Y)

    # Backpropagation: Define the tensorflow optimizer. Use an AdamOptimizer.

    optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost)

    # Initialize all the variables
    init = tf.global_variables_initializer()

    # Start the session to compute the tensorflow graph
    with tf.Session() as sess:

        # Run the initialization
        sess.run(init)

        # Do the training loop
        for epoch in range(num_epochs):

            epoch_cost = 0.                       # Defines a cost related to an epoch
            num_minibatches = int(m / minibatch_size) # number of minibatches of size minibatch_size in the train set
            seed = seed + 1
            minibatches = random_mini_batches(X_train, Y_train, minibatch_size, seed)

            for minibatch in minibatches:

                # Select a minibatch
                (minibatch_X, minibatch_Y) = minibatch

                # IMPORTANT: The line that runs the graph on a minibatch.
                # Run the session to execute the "optimizer" and the "cost", the feedict should contain a minibatch for (X,Y).

                _ , minibatch_cost = sess.run([optimizer, cost], feed_dict={X: minibatch_X, Y: minibatch_Y})

                epoch_cost += minibatch_cost / num_minibatches

            # Print the cost every epoch
            if print_cost == True and epoch % 100 == 0:
                print ("Cost after epoch %i: %f" % (epoch, epoch_cost))
            if print_cost == True and epoch % 5 == 0:
                costs.append(epoch_cost)

        # plot the cost
        plt.plot(np.squeeze(costs))
        plt.ylabel('cost')
        plt.xlabel('iterations (per tens)')
        plt.title("Learning rate =" + str(learning_rate))
        plt.show()

        # lets save the parameters in a variable
        parameters = sess.run(parameters)
        print("Parameters have been trained!")

        # Calculate the correct predictions
        correct_prediction = tf.equal(tf.argmax(Z3), tf.argmax(Y))

        # Calculate accuracy on the test set
        accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))

        print("Train Accuracy:", accuracy.eval({X: X_train, Y: Y_train}))
        print("Test Accuracy:", accuracy.eval({X: X_test, Y: Y_test}))

        return parameters

parameters = model(X_train, Y_train, X_test, Y_test)

Cost after epoch 0: 1.855702
Cost after epoch 100: 1.016458
Cost after epoch 200: 0.733102
Cost after epoch 300: 0.572940
Cost after epoch 400: 0.468774
Cost after epoch 500: 0.381021
Cost after epoch 600: 0.313822
Cost after epoch 700: 0.254158
Cost after epoch 800: 0.203829
Cost after epoch 900: 0.166421
Cost after epoch 1000: 0.141486
Cost after epoch 1100: 0.107580
Cost after epoch 1200: 0.086270
Cost after epoch 1300: 0.059371
Cost after epoch 1400: 0.052228

Parameters have been trained!
Train Accuracy: 0.999074
Test Accuracy: 0.716667

Tensorflow Tutorial, Neural Network Using Tensorflow .py


# 1d linear regression.
# Make the data and plot it.

import matplotlib.pyplot as plt
import numpy as np
from utils.linreg_model import LinregModel

def make_fun_1d(fun_type):
    if fun_type == 'linear':
        params_true = np.array([1, 1])
        true_fun = lambda x: params_true[1] + params_true[0]*x
        ttl = 'w*x + b'
    if fun_type == 'sine':
        params_true = np.array([1, 1])
        true_fun = lambda x: params_true[1] + params_true[0]*np.sin(x)
        ttl = 'w*sin(x) + b'
    if fun_type == 'quad':
        # 'thibaux' parameters from here:
        #https://github.com/probml/pmtk3/blob/master/matlabTools/stats/polyDataMake.m
         #w = [-1.5; 1/9];
        #fun = @(x) w(1)*x + w(2)*x.^2;
        params_true = np.array([1, 1])
        true_fun = lambda x: params_true[0]*x + params_true[1]*np.square(x)
        ttl = 'w*x^2 + b'
    return params_true, true_fun, ttl

# Sample (x,y) pairs from a noisy function
def make_data_linreg_1d(N, fun_type, matlab_hack=False):
    if '-' in fun_type:
        parts = fun_type.split('-')
        fun_type = parts[0]
        centered = (parts[1] == 'centered')
    else:
        centered = True
    params_true, true_fun, fun_name = make_fun_1d(fun_type)
    if centered:
        xtrain = np.random.normal(0, 3, N)
    else:
        xtrain = np.linspace(0, 20, N)
    ytrain_clean = true_fun(xtrain)
    sigma2 = 1
    noise = np.random.normal(0, 1, xtrain.shape) * np.sqrt(sigma2)
    Ytrain = ytrain_clean + noise
    Xtrain = np.reshape(xtrain, (N, 1))
    if matlab_hack:
        # Match matlab's https://github.com/probml/pmtk3/blob/master/demos/contoursSSEdemo.m
        Ytrain = np.array([3.560, 1.831, 0.924, 1.475, 0.531, 0.686, 2.720, 3.061, -1.233, 1.369, 2.990, 1.546, 3.425,
        1.406, 3.306, 0.729, 4.050, 1.879, 0.313, 0.369])
        xtrain = np.array([1.749, 0.133, 0.325, -0.794, 0.315, -0.527, 0.932, 1.165, -2.046, -0.644, 1.741, 0.487, 1.049,
        1.489, 1.271, -1.856, 2.134, 1.436, -0.917, -1.106])
        N = len(xtrain)
        Xtrain = np.reshape(xtrain, [N,1])
    return Xtrain, Ytrain, params_true, true_fun, fun_name

# Plot 2d error surface around model's parameter vaulues
def plot_error_surface_2d(loss_fun, params_opt, params_true, fun_type, ax=None):
    if ax is None:
        fig = plt.figure()
        ax = fig.add_subplot(111)
    # Choose the range to make a pretty plot
    if fun_type == 'quad':
        w0_range = [-1, 2]
        w1_range = [-1, 6]
    elif fun_type == 'sine':
        w0_range = [-3, 3]
        w1_range = [-1, 3]
    else:
        w0_range = [-1, 3]
        w1_range = [-1, 3]
    w0s = np.linspace(w0_range[0], w0_range[1], 100)
    w1s = np.linspace(w1_range[0], w1_range[1], 100)
    w0_grid, w1_grid = np.meshgrid(w0s, w1s)
    lossvec = np.vectorize(loss_fun)
    z = lossvec(w1_grid, w0_grid)
    cs = ax.contour(w1s, w0s, z)
    ax.clabel(cs)
    ax.plot(params_opt[1], params_opt[0], 'rx', markersize=14)
    ax.plot(params_true[1], params_true[0], 'k+', markersize=14)
    return ax

def plot_param_trace_2d(params_trace, ax):
    '''Plot 2d trajectory of parameters on top of axis,
    param_trace is list of weight vectors'''
    n_steps = len(params_trace)
    xs = np.zeros(n_steps)
    ys = np.zeros(n_steps)
    for step in range(1, n_steps):
        xs[step] = params_trace[step][1]
        ys[step] = params_trace[step][0]
    ax.plot(xs, ys, 'o-')

def plot_data_and_predictions_1d(xtrain, ytrain, true_fun, pred_fun, ax=None):
    if ax is None:
        fig = plt.figure()
        ax = fig.add_subplot(111)
    ax.plot(xtrain, ytrain, 'o', label='observed')
    x_range = np.linspace(np.min(xtrain), np.max(xtrain), 100)
    x_range = np.reshape(x_range, [100,1])
    yhat_range = pred_fun(x_range)
    ax.plot(x_range, yhat_range, 'r--', label='predicted')
    y_range = true_fun(x_range)
    ax.plot(x_range, y_range, 'k-', label='truth')
    return ax

def main():
    for fun_type in ['linear', 'quad', 'sine']:
        np.random.seed(1)
        N = 20
        Xtrain, Ytrain, params_true, true_fun, ttl = make_data_linreg_1d(N, fun_type)

        model = LinregModel(1, True)
        params_ols, loss_ols = model.ols_fit(Xtrain, Ytrain)
        print(ttl)
        print(params_ols)

        # Plot data
        predict_fun = lambda x: model.prediction(params_ols, x)
        ax = plot_data_and_predictions_1d(Xtrain, Ytrain, true_fun, predict_fun)
        ax.set_title(ttl)

        # Plot error surface
        loss_fun = lambda w0, w1: model.objective([w0, w1], Xtrain, Ytrain)
        ax  = plot_error_surface_2d(loss_fun, params_ols, params_true, fun_type)
        ax.set_title(ttl)
    plt.show()

if __name__ == "__main__":
    main()


import numpy as np
import pandas as pd
import datetime

# 21
ser = pd.Series(["01 Jan 2010", "02-02-2011", "20120303", "2013/04/04",
                 "2014-05-05", "2015-06-06-T12:20"])
ser = pd.to_datetime(ser)

# 22 Get day of month, week number, day of year, day of week
print("Day of month:\n", list(ser.dt.day))
print("Week number:\n", list(ser.dt.weekofyear))
print("Day of year:\n", list(ser.dt.dayofyear))
print("Day of week:\n", list(ser.dt.weekday_name))

# 23 Convert year-month string to dates corresponding to 4th of months
ser = pd.Series(["Jan 2010", "Feb 2011", "Mar 2012"])
ser = pd.Series("04 " + ser)  # my solution
ser = pd.to_datetime(ser)

ser = pd.Series(["Jan 2010", "Feb 2011", "Mar 2012"])  # more elegant solution
ser.map(lambda x: pd.to_datetime("04 " + x))

ser = pd.Series(["Jan 2010", "Feb 2011", "Mar 2012"])
ser = pd.to_datetime(["04 " + x for x in ser])  # more pythonic solution

# 24 Filter words that contain at least 2 vowels
ser = pd.Series(["Apple", "Orange", "Plan", "Python", "Money"])

def count_vowels(s):  # my solution
    vowels = 0
    for c in s:
        if c.lower() in "aeiou":
            vowels += 1
    return vowels

ser[ser.map(count_vowels) >= 2]

# Filter valid emails from a list using regex
emails = pd.Series(['buying books at amazom.com', 'rameses@egypt.com',
                    'matt@t.co', 'narendra@modi.com'])
pattern ='[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}'
emails[emails.str.contains(pattern)]

# 26 Get mean of series grouped by another series
fruit = pd.Series(np.random.choice(["apple", "banana", "carrot"], 10))
weights = pd.Series(np.linspace(1, 10, 10))
weights.groupby(fruit).mean()

# 27 Compute the euclidian distances between two series
p = pd.Series(np.arange(1, 11))
q = p[::-1]
q.index = range(0,len(q))

sum((p - q) ** 2) ** (1 / 2)  # my solution
np.linalg.norm(p - q)  # using a function

# 28 Find all peaks in numeric series
ser = pd.Series([2, 10, 3, 4, 9, 10, 2, 7, 3])
# 1, 5, 7
ser[np.sign(ser.diff(2)) < 0].index - 1
ser.loc(np.diff(np.sign(np.diff(ser))) == -2)
np.diff(np.sign(np.diff(ser)))


"""
Project: Visual Odometry
Name : Heru-05 | M09158023
Date
"""

import os
import numpy as np
import cv2
import math

# A class for computing a moving average (mean value) with a given window size.
# Optionally, you can also compute standard devitation of the signal and standard deviation of the average
class MovingAverage:
    def __init__(self, average_width = 10, compute_sigma = False):
        self._average_width = average_width
        self._idx_ring = 0
        self._average = 0
        self._sigma2 = 0
        self._is_init = False
        self._is_compute_sigma = compute_sigma
        self._one_over_average_width_min_one = 1./(average_width-1)
        self._ring_buffer = np.zeros(average_width)

    def init(self, initVal=None):
        if initVal is None:
            initVal = 0.
        self._ring_buffer = np.full(self._average_width, initVal, dtype=np.float32)
        self._average	= initVal;
        self._sigma2	= 0;
        self._is_init	= True;

    def getAverage(self, new_val=None):
        if not self._is_init:
            self.init(new_val)
        if new_val is None:
            return self._average
        averageOld	= self._average
        oldVal		= self._ring_buffer[self._idx_ring]
        self._average += (new_val - oldVal)/self._average_width
        if self._is_compute_sigma:
            self._sigma2	=  self._sigma2 + self._one_over_average_width_min_one*(self._average_width*(averageOld*averageOld - self._average*self._average) - oldVal*oldVal + newVal*newVal)
        self._ring_buffer[self._idx_ring]	= new_val
        self._idx_ring = (self._idx_ring + 1) % self._average_width
        return self._average

    def getSigma(self):
        return  math.sqrt(max(self._sigma2,0.))


"""
Wrapper for activation functions and their derivatives
to be used with the DNN classes
"""

import numpy as np

# Logistic
def myLogistic(X):
    return 1.0 / (1.0 + np.exp(-X))

def myLogisticPrime(X):
    S = myLogistic(X)
    return np.multiply(S, 1.0 - S)

# Hyperbolic tangent
def myTanh(X):
    return np.tanh(X)

def myTanhPrime(X):
    return 1 - np.square(np.tanh(X))

# Rectified linear units
def myRelu(X):
    return np.maximum(0.0, X)

def myReluPrime(X):
    return (X > 0.0).astype(X.dtype)

# Absolute value (fully rectified)
def myAbs(X):
    return np.abs(X)

def myAbsPrime(X):
    return np.sign(X)

# Squared
def mySquare(X):
    return np.square(X)

def mySquarePrime(X):
    return X

# Half squared
def myHalfSquare(X):
    return myRelu(mySquare(X))

def myHalfSquarePrime(X):
    return myRelu(X)

## activation functions are regitered in the following dictionary
func_list = {'sigmoid':(myLogistic, myLogisticPrime),     \
             'tanh':(myTanh, myTanhPrime),        \
             'relu':(myRelu, myReluPrime),        \
             'abs':(myAbs, myAbsPrime),         \
             'square':(mySquare, mySquarePrime),      \
             'half_square':(myHalfSquare, myHalfSquarePrime)}


#Eulers method
import numpy as np

def dy(ynew,xnew,y,x,h):
    dyvalue = y-x
    return dyvalue
 #Note: change the derivative function based on question!!!!!!  Example: y-x

y0 = 0.5  #float(input"what is the y(0)?")

h = 0.1 #float(input"h?")

x_final = 0.3 #float(input"x_final")

#initiating input variables
x = 0
y = y0
# remember to change yn+1 and xn+1 values if you already know them!!!
ynew = 0
xnew = 0
i = 0

#####################################################
iterations = x_final/h

while x <= x_final:
    derivative_of_y = dy(ynew,xnew,y,x,h)
    xnew = x + h
    ynew = y + (xnew - x)*(derivative_of_y)
    print("iteration:        ____            ")
    print(i)
    print("\n")
    print("x = ")
    print(xnew)
    print("\n")
    print("y = ")
    print(ynew)
    x = xnew
    y = ynew
    i+=1


#
import math
import numpy as np

class HoltWinters(object):
    def __init__(self):
        self.name = 'HoltWinters'

    def startup(self):
        self.predict_by_mean()

    def predict_by_mean(self):
        y = np.array([3,10,12,13,12,10,12], dtype=np.float32)
        return np.mean(y)

    def weighted_average(self, series, weights):
        mean = 0.0
        weights.reverse()
        for i in range(len(weights)):
            mean += series[-i-1] * weights[i]
        return mean

    def expopential_smoothing(self, series, alpha):
        result = [series[0]]
        for t in range(1, len(series)):
            result.append(alpha * series[t] + (1 - alpha) * result[t-1])
        return result

    def double_exponential_smoothing(self, series, alpha, beta):
        result = [series[0]]
        for n in range(1, len(series)+1):
            if n == 1:
                level, trend = series[0], series[1] - series[0]
            if n >= len(series): # we are forecasting
              value = result[-1]
            else:
              value = series[n]
            last_level, level = level, alpha*value + (1-alpha)*(level+trend)
            trend = beta*(level-last_level) + (1-beta)*trend
            result.append(level+trend)
        return result

    def initial_trend(self, series, slen):
        sum = 0.0
        for i in range(slen):
            sum += float(series[i+slen] - series[i]) / slen
        return sum / slen

    def initial_seasonal_components(self, series, slen):
        seasonals = {}
        season_averages = []
        n_seasons = int(len(series)/slen)
        # compute season averages
        for j in range(n_seasons):
            season_averages.append(sum(series[slen*j:slen*j+slen])/float(slen))
        # compute initial values
        for i in range(slen):
            sum_of_vals_over_avg = 0.0
            for j in range(n_seasons):
                sum_of_vals_over_avg += series[slen*j+i]-season_averages[j]
            seasonals[i] = sum_of_vals_over_avg/n_seasons
        return seasonals

    def triple_exponential_smoothing(self, series, slen, alpha, beta, gamma, n_preds):
        result = []
        seasonals = self.initial_seasonal_components(series, slen)
        for i in range(len(series)+n_preds):
            if i == 0: # initial values
                smooth = series[0]
                trend = self.initial_trend(series, slen)
                result.append(series[0])
                continue
            if i >= len(series): # we are forecasting
                m = i - len(series) + 1
                result.append((smooth + m*trend) + seasonals[i%slen])
            else:
                val = series[i]
                last_smooth, smooth = smooth, alpha*(val-seasonals[i%slen]) + (1-alpha)*(smooth+trend)
                trend = beta * (smooth-last_smooth) + (1-beta)*trend
                seasonals[i%slen] = gamma*(val-smooth) + (1-gamma)*seasonals[i%slen]
                result.append(smooth+trend+seasonals[i%slen])
        return result


from pandas import read_csv
from matplotlib import pyplot
from statsmodels.tsa.stattools import adfuller

series = read_csv('../data/daily-total-female-births.csv', header=0, index_col=0, squeeze=True)

series.plot()
pyplot.show()

series.hist()
pyplot.show()

# Summary stats
X = series.values
split = round(len(X) / 2)
X1, X2 = X[0:split], X[split:]
mean1, mean2 = X1.mean(), X2.mean()
var1, var2 = X1.var(), X2.var()
print('mean1=%f, mean2=%f' % (mean1, mean2))
print('variance1=%f, variance2=%f' % (var1, var2))

# Augmented Dickey-Fuller test for stationarity (H0: series has unit root; i.e., is non-stationary)
result = adfuller(X)
print('ADF Statistic: %f' % result[0])
print('p-value: %f' % result[1])
print('Critical Values:')
for key, value in result[4].items():
    print('\t%s: %.3f' % (key, value))


"""
Notes
-----
Build an array of power levels
Slide a 3x3 window & calculate sum of power levels
"""
import numpy as np
from typing import Tuple

def build_power_levels(serial_no: int) -> np.ndarray:
    n_x = 300
    n_y = 300
    power_levels = np.empty((n_x, n_y), dtype=int)

    for x in range(n_x):
        for y in range(n_y):
            power_levels[x, y] = get_power_level(x + 1, y + 1, serial_no)

    return power_levels

def get_power_level(x: int, y: int, serial_no: int) -> int:
    rack_id = x + 10
    power_level = (rack_id * y + serial_no) * rack_id
    power_level = power_level // 100 % 10 - 5
    return power_level

def get_largest_square(power_levels: np.ndarray,
                       width: int = 3,
                       height: int = 3) -> Tuple[int, int, int]:
    best_x = np.nan
    best_y = np.nan
    best_power_level = -np.inf
    for x in range(0, power_levels.shape[0] - width + 2):
        for y in range(0, power_levels.shape[1] - height + 2):
            square = power_levels[x:(x + width), y:(y + height)]
            power_level = square.sum()
            if power_level > best_power_level:
                best_x = x
                best_y = y
                best_power_level = power_level

    return (best_x + 1, best_y + 1, best_power_level)

def get_largest_total_square(power_levels: np.ndarray):
    best_x = np.nan
    best_y = np.nan
    best_size = np.nan
    best_power_level = -np.inf
    for size in range(100):
        x, y, power_level = get_largest_square(power_levels,
                                               width=size,
                                               height=size)
        if power_level > best_power_level:
            best_x = x
            best_y = y
            best_size = size
            best_power_level = power_level
        elif power_level < 0:
            break

    return (best_x, best_y, best_size, best_power_level)

assert get_power_level(3, 5, 8) == 4
assert get_power_level(122, 79, 57) == -5
assert get_power_level(217, 196, 39) == 0
assert get_power_level(101, 153, 71) == 4

test_power_levels_18 = build_power_levels(18)
assert get_largest_square(test_power_levels_18) == (33, 45, 29)

test_power_levels_42 = build_power_levels(42)
assert get_largest_square(test_power_levels_42) == (21, 61, 30)

assert get_largest_total_square(test_power_levels_18) == (90, 269, 16, 113)
assert get_largest_total_square(test_power_levels_42) == (232, 251, 12, 119)

power_levels = build_power_levels(4455)
print(get_largest_square(power_levels))
print(get_largest_total_square(power_levels))


from lib.operators.Operator import Operator
import numpy as np

class Sigmoid(Operator):
    def __init__(self):
        super().__init__()

    @staticmethod
    def function(x):
        return 1 / (1 + np.exp(-x))

    @staticmethod
    def derivative(x):
        return np.multiply(x, (1 - x))


"""
 linear_regression_SGD.py  (author: Anson Wong / git: ankonzoid)
"""
import os
import numpy as np
import pandas as pd
class LinearRegressorSGD:
	def __init__(self):
		pass
	def fit(self, X, y):
		print("Fitting...")
		N, d = X.shape
		a_fit = np.random.normal(size=d + 1)
		loss_tolerance = 1e-6
		fit_tolerance = 1e-4
		eta = 1e-6
		converge = False
		loss = 9e99
		iter = 0
		while not converge:
			i_random = np.random.choice(N)
			gradient = np.zeros(d + 1)
			y_hat_i = a_fit[0] + np.dot(a_fit[1:], X[i_random])
			y_i = y[i_random]
			gradient[0] += 2 * (y_hat_i - y_i)
			gradient[1:] += 2 * (y_hat_i - y_i) * X[i_random, 0:]
			a_fit_new = a_fit - eta * gradient
			y_pred = []
			for x in X:
				y_pred_i = a_fit_new[0] + np.dot(a_fit_new[1:], x)
				y_pred.append(y_pred_i)
			y_pred = np.array(y_pred)
			loss_new = np.linalg.norm(y_pred - y) ** 2 / N
			if iter % N:
				print("loss = {}".format(loss))
			if np.abs(loss_new - loss) < loss_tolerance and np.linalg.norm(a_fit_new - a_fit) < fit_tolerance:
				converge = True
			a_fit = a_fit_new
			loss = loss_new
			iter += 1
		self.a_fit = a_fit
	def predict(self, X):
		y_pred = []
		for x in X:
			y_pred_i = self.a_fit[0] + np.dot(self.a_fit[1:], x)
			y_pred.append(y_pred_i)
		y_pred = np.array(y_pred)
		return y_pred
if __name__ == "__main__":
	X = np.arange(100).reshape(-1, 1)
	y = 0.4 * X.flatten() + 3 + np.random.uniform(-10, 10, size=(100,))
	model = LinearRegressorSGD()
	model.fit(X, y)
	y_pred = model.predict(X)
	mse = ((y_pred - y) ** 2).mean(axis=0)
	print("mse =", mse)
	import matplotlib.pyplot as plt
	plt.figure(1)
	plt.plot(X.flatten(), y, "o")
	plt.plot(X.flatten(), y_pred, "r")
	plt.show()