import scipy.integrate, scipy.stats, scipy.optimize
import numpy as np, pandas as pd

def poilog_exp_integrand(x, n, mu, sigma):
    '''
    The part of the poilog integral that is inside the exponent.
    '''
    return n * x - np.exp(x) - 0.5 * ((x - mu) / sigma) ** 2

def poilog_exp_integrand_max(n, mu, sigma):
    '''
    Find the maximum value and position of the exponential part of the integrand.

    Returns: (float, float)
      The position and value of the maximum
    '''
    f = lambda x: -poilog_exp_integrand(x, n, mu, sigma)
    fprime = lambda x: -(n - np.exp(x) - (x - mu) / sigma ** 2)
    res = scipy.optimize.fmin_bfgs(f, 0.0, fprime, disp=False, full_output=True)
    xopt, fopt, gopt, Bopt, func_calls, grad_calls, warnflag = res

    return xopt, -fopt

def poilog_upper_bound(n, mu, sigma, fold=1e-9, guess=1.0, guess_multiplier=2.0):
    '''
    Pick a reasonable upper bound for the poilog integral. Start at the place where
    the integrand is maximized, then go out until the integrand
    falls to some fold of its maximum value.

    returns: float
    '''

    xopt, fopt = poilog_exp_integrand_max(n, mu, sigma)
    f = lambda x: poilog_exp_integrand(x, n, mu, sigma) - fopt - np.log(fold)

    while f(xopt + guess) > 0:
        guess *= guess_multiplier

    ub = scipy.optimize.brentq(f, xopt, xopt + guess)

    return ub

def poilog_pmf_notrunc(n, mu, sigma):
    '''
    Probability mass function without truncation
    '''

    if n < 0:
        raise ValueError("poilog takes nonnegative integers")

    lb = -np.inf
    ub = poilog_upper_bound(n, mu, sigma)

    # I put the factorial inside the exponent because it helps the whole thing behave better
    constant = 1.0 / (sigma * np.sqrt(2 * np.pi))
    fac = scipy.special.gammaln(n + 1)
    f = lambda x: constant * np.exp(n * x - np.exp(x) - 0.5 * ((x - mu) / sigma) ** 2 - fac)

    val, error = scipy.integrate.quad(f, lb, ub)
    return val

def poilog_pmf(n, mu, sigma, trunc=True):
    '''
    Probability mass function (with optional zero truncation)
    '''

    if trunc:
        if n == 0:
            return 0.0
        else:
            return poilog_pmf_notrunc(n, mu, sigma) / (1.0 - poilog_pmf_notrunc(0, mu, sigma))
    else:
        return poilog_pmf_notrunc(n, mu, sigma)

def poilog_cdf(ns, mu, sigma, trunc=True):
    '''
    Cumulative distribution function

    ns: sequence of integers
      number of counts for each sequence
    mu, sigma: float
      poilog distribution parameters
    trunc: bool
      poilog distribution parameter

    returns: list of floats
    '''

    # compute all the values up to the biggest n
    all_pmfs = [poilog_pmf(n, mu, sigma, trunc) for n in range(int(max(ns)) + 1)]
    all_cdfs = np.cumsum(all_pmfs)

    return [all_cdfs[n] for n in ns]

def poilog_ll(ns, mu, sigma, trunc=True, threshold=1e-120):
    '''
    Log likelihood of a list of counts
    '''

    ll = 0.0
    for n, counts in scipy.stats.itemfreq(ns):
        pmf = poilog_pmf(n, mu, sigma, trunc)

        # log function complains if it sees very small values, so we make our own cutoff
        if pmf > threshold:
            ll += counts * np.log(pmf)

    return ll

def poilog_fit(ns, trunc=True, x0=None, full_output=False):
    '''
    Maximum likelihood estimation fit

    x0: (float, float)
      The starting mu and sigma for the MLE optimization. If None, then a guess will be supplied.
    full_output: bool
      If True, then also return the OptimizeResult object

    Returns: (float, float) or (float, float, OptimizeResult)
      Optimal mu and sigma (and optionally the rest of the data)
    '''

    ns = np.array(ns)
    if trunc:
        ns = ns[ns > 0]

    if x0 is None:
        x0 = [np.mean(np.log(ns)), np.log(np.std(np.log(ns)))]

    f = lambda x: -poilog_ll(ns, x[0], np.exp(x[1]), trunc)

    res = scipy.optimize.minimize(f, x0, method='Nelder-Mead')
    mu_opt, log_sigma_opt = res.x
    sigma_opt = np.exp(log_sigma_opt)

    if full_output:
        return mu_opt, sigma_opt, res
    else:
        return mu_opt, sigma_opt


import numpy as np

def get_L1_dist(list1, list2):
    return np.linalg.norm(np.subtract(np.array(list1),np.array(list2)),1)

def get_L2_dist(list1, list2):
    return np.linalg.norm(np.subtract(np.array(list1),np.array(list2)),2)


import numpy as np
from abc import ABC, abstractmethod

def create_weight_matrix(nrows, ncols):
    """Create a weight matrix with normally distributed random elements."""
    return np.random.default_rng().normal(loc=0, scale=1/(nrows*ncols), size=(nrows, ncols))

def create_bias_vector(length):
    """Create a bias vector with normally distributed random elements."""
    return create_weight_matrix(length, 1)

class ActivationFunction:
    """Class to be inherited by activation functions."""
    @abstractmethod
    def f(self, x):
        """The method that implements the function."""
        pass

    @abstractmethod
    def df(self, x):
        """Derivative of the function with respect to its input."""
        pass

class LeakyReLU(ActivationFunction):
    """Leaky Rectified Linear Unit."""
    def __init__(self, leaky_param=0.1):
        self.alpha = leaky_param

    def f(self, x):
        return np.maximum(x, x*self.alpha)

    def df(self, x):
        return np.maximum(x > 0, self.alpha)

class Sigmoid(ActivationFunction):
    def f(self, x):
        return 1/(1 + np.exp(-x))

    def df(self, x):
        return self.f(x) * (1 - self.f(x))

class LossFunction:
    """Class to be inherited by loss functions."""
    @abstractmethod
    def loss(self, values, expected):
        """Compute the loss of the computed values with respect to the expected ones."""
        pass

    @abstractmethod
    def dloss(self, values, expected):
        """Derivative of the loss with respect to the computed values."""
        pass

class MSELoss(LossFunction):
    """Mean Squared Error Loss function."""
    def loss(self, values, expected):
        return np.mean((values - expected)**2)

    def dloss(self, values, expected):
        return 2*(values - expected)/values.size

class CrossEntropyLoss(LossFunction):
    """Cross entropy loss function following the pytorch docs."""
    def loss(self, values, target_class):
        return -values[target_class, 0] + np.log(np.sum(np.exp(values)))

    def dloss(self, values, target_class):
        d = np.exp(values)/np.sum(np.exp(values))
        d[target_class, 0] -= 1
        return d

class Layer:
    """Model the connections between two sets of neurons in a network."""
    def __init__(self, ins, outs, act_function):
        self.ins = ins
        self.outs = outs
        self.act_function = act_function

        self._W = create_weight_matrix(self.outs, self.ins)
        self._b = create_bias_vector(self.outs)

    def forward_pass(self, x):
        """Compute the next set of neuron states with the given set of states."""
        return self.act_function.f(np.dot(self._W, x) + self._b)

class NeuralNetwork:
    """A series of connected, compatible layers."""
    def __init__(self, layers, loss_function, learning_rate):
        self._layers = layers
        self._loss_function = loss_function
        self.lr = learning_rate

        # Check layer compatibility
        for (from_, to_) in zip(self._layers[:-1], self._layers[1:]):
            if from_.outs != to_.ins:
                raise ValueError("Layers should have compatible shapes.")

    def forward_pass(self, x):
        out = x
        for layer in self._layers:
            out = layer.forward_pass(out)
        return out

    def loss(self, values, expected):
        return self._loss_function.loss(values, expected)

    def train(self, x, t):
        """Train the network on input x and expected output t."""

        # Accumulate intermediate results during forward pass.
        xs = [x]
        for layer in self._layers:
            xs.append(layer.forward_pass(xs[-1]))

        dx = self._loss_function.dloss(xs.pop(), t)
        for layer, x in zip(self._layers[::-1], xs[::-1]):
            # Compute the derivatives
            y = np.dot(layer._W, x) + layer._b
            db = layer.act_function.df(y) * dx
            dx = np.dot(layer._W.T, db)
            dW = np.dot(db, x.T)
            # Update parameters.
            layer._W -= self.lr * dW
            layer._b -= self.lr * db

if __name__ == "__main__":
    """Demo of a network as a series of layers."""
    net = NeuralNetwork([
        Layer(2, 4, LeakyReLU()),
        Layer(4, 4, LeakyReLU()),
        Layer(4, 3, LeakyReLU()),
    ], MSELoss(), 0.001)
    t = np.zeros(shape=(3,1))

    loss = 0
    for _ in range(100):
        x = np.random.normal(size=(2,1))
        loss += net.loss(net.forward_pass(x)[-1], t)
    print(loss)

    for _ in range(10000):
        net.train(np.random.normal(size=(2,1)), t)

    loss = 0
    for _ in range(100):
        x = np.random.normal(size=(2,1))
        loss += net.loss(net.forward_pass(x)[-1], t)
    print(loss)


import numpy as np

import helpers

positions = np.array([16,1,2,0,4,2,7,1,2,14])#helpers.read_input_at_once(__file__, 'int')).squeeze()

# sort positions
positions = np.sort(positions)
# index of median element
med = positions.shape[0]//2

def part_1():
    # get median (that's the optimal position)
    if positions.shape[0] % 2 == 0:
        optimal_pos = positions[med]
    else:
        optimal_pos = positions[med] + positions[med+1]
        optimal_pos /= 2

    fuel_spent = np.abs(positions - optimal_pos).sum()

    return fuel_spent

def part_2():

    mean = positions.mean().astype(int)
    optimal_pos = mean
    error = np.sign(positions - optimal_pos).mean() // 2

    while optimal_pos != mean + error:
        print(error)
        optimal_pos += error.round(0).astype(int)
        error = np.sign(positions - optimal_pos).mean() // 2

    print(optimal_pos)
    steps = np.abs(positions - optimal_pos)
    fuel_spent = ((steps * (steps + 1)).sum()) / 2

    return fuel_spent

print(part_2())

Python/Day 7: The Treachery of Whales 1.py


import numpy as np

import os
os.environ["KMP_DUPLICATE_LIB_OK"]="TRUE"

# === Create data and simulate results =====

x_data = np.random.randn(2000,3)
w_real = [0.3,0.5,0.1]
b_real = -0.2
noise = np.random.randn(1,2000)*0.1
y_data = np.matmul(w_real, x_data.T) + b_real + noise

import tensorflow as tf

NUM_STEPS = 10
g = tf.Graph()
wb_=[]
with g.as_default():
    x = tf.placeholder(tf.float32, shape=[None,3])
    y_true = tf.placeholder(tf.float32, shape=None)

    with tf.name_scope('inference') as scope:
        w = tf.Variable([[0,0,0]], dtype=tf.float32, name='weights')
        b = tf.Variable(0, dtype=tf.float32, name='bias')
        y_pred = tf.matmul(w, tf.transpose(x)) + b

    with tf.name_scope('loss') as scope:
        loss = tf.reduce_mean(tf.square(y_true-y_pred))

    with tf.name_scope('train') as scope:
        learning_rate = 0.5
        optimizer = tf.train.GradientDescentOptimizer(learning_rate)
        train = optimizer.minimize(loss)

    # Before starting, initialize the variables.  We will 'run' this first.
    init = tf.global_variables_initializer()
    with tf.Session() as sess:
        sess.run(init)
        for step in range(NUM_STEPS):
            sess.run(train, {x: x_data, y_true: y_data})
            if step%5 == 0:
                print(step, sess.run([w,b]))
                wb_.append(sess.run([w,b]))

        print(10, sess.run([w,b]))

print(wb_)
print('#' * 30)
print(w_real, b_real)


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

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

p_a = df[df['fico']>700].shape[0]/df.shape[0]
print(p_a)

p_b = df[df['purpose']=='debt_consolidation'].shape[0]/df.shape[0]
print(p_b)

df1 = df[df['purpose']=='debt_consolidation']

p_a_b = df1[df1['fico']>700].shape[0]/df1.shape[0]

print(p_a_b)

result = (p_a == p_a_b)
print(result)
# code ends here

# --------------
# code starts here
prob_lp = df[df['paid.back.loan']=='Yes'].shape[0]/df.shape[0]
print(prob_lp)

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

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

prob_pd_cs = new_df[new_df['credit.policy']=='Yes'].shape[0]/new_df.shape[0]
print(prob_pd_cs)

bayes = (prob_pd_cs*prob_lp)/prob_cs

print(bayes)
# code ends here

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

df.purpose.value_counts(normalize=True).plot(kind='bar')
df1 = df[df['paid.back.loan']=='No']
df1.purpose.value_counts(normalize=True).plot(kind='bar')
# code ends here

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

inst_median = df.installment.median()
print(inst_median)
inst_mean  = df.installment.mean()
print(inst_mean)

df.installment.hist(normed = True, bins=50)
# code ends here


from math import log
import numpy as np

from independence_tests.corr import pearson

def _check_xy(x, y):
    assert x.shape[0] == y.shape[0]
    if x.ndim > 1:
        assert x.shape[1] == 1
        x = x.ravel()
    if y.ndim > 1:
        assert y.shape[1] == 1
        y = y.ravel()
    return x, y

def _get_bins(bins, x, y):
    """
    If bins is not set, estimate them according to
    Hacine-Gharbi and Ravier (2018);
    cf. "de Prado, Marcos Lopez. Machine Learning for Asset Managers.
    Cambridge University Press, 2020."
    """
    if bins is None:
        corr = pearson(x, y)[0]
        if abs(corr) < 0.99:
            # optimal number of bins (Hacine-Gharbi and Ravier (2018))
            ratio_ = (24.0 * x.shape[0]) / (1.0 - corr ** 2)
            bins_ = (0.5 * (1.0 + (1.0 + ratio_) ** 0.5)) ** 0.5
            bins = int(round(bins_))
        else:
            bins = 10
    return bins

def _mi(count_xy):
    """
    Following sklearn.metrics.mutual_info_score
    """
    count_x = count_xy.sum(axis=1)
    count_y = count_xy.sum(axis=0)
    count_total = count_x.sum()

    nz_x, nz_y = np.nonzero(count_xy)
    nz_values = count_xy[nz_x, nz_y]
    outer = count_x[nz_x] * count_y[nz_y]

    mi = nz_values * (np.log(nz_values) - np.log(outer) + log(count_total))
    return mi.sum() / count_total, count_x, count_y


import numpy as np
import math
from scipy import signal

# Return a box filter of size n by n
# Requires n to be an odd integer
def boxfilter(n):
  assert(n % 2 == 1), "Dimension must be odd"
  # Create n x n array, every element = n^-2
  return np.full((n, n), pow(n, -2))

# Return a 1D Gaussian filter
# Fix length of filter array to (6 * sigma) rounded up to next odd integer
def gauss1d(sigma):
  # Max distance from center of the array
  # = floor(((6 * sigma) rounded up to next odd integer)/2)
  # = (6 * sigma) rounded up to next integer
  maxDistFromCenter = int(np.ceil(6 * sigma)) / 2
  distsFromCenter = np.arange(-maxDistFromCenter, maxDistFromCenter + 1)
  # unnormalizedFilter[i] = exp(-x^2 / (2*sigma^2)), where x = distance of i from array center
  unnormalizedFilter = np.exp(-pow(distsFromCenter, 2) / (2.0 * pow(sigma, 2)))
  return normalize(unnormalizedFilter)

# Return a 2D Gaussian filter
# Fix side lengths to (6 * sigma) rounded up to next odd integer
def gauss2d(sigma):
  gauss1dArray = gauss1d(sigma)
  # The 2D Gaussian filter is the convolution of the 1D Gaussian and its transpose
  reshapedTo2D = gauss1dArray.reshape(1,gauss1dArray.size) # Reshape to allow us to transpose
  unnormalizedFilter = signal.convolve2d(reshapedTo2D, reshapedTo2D.transpose())
  return normalize(unnormalizedFilter)

# Return the result of applying a 2D Gaussian filter convolution to an input array
def gaussconvolve2d(array, sigma):
  gaussFilter = gauss2d(sigma)
  return signal.convolve2d(array, gaussFilter, 'same')

# Normalize an array so that its elements sum to approximately 1.00
def normalize(numpyArray):
  return numpyArray / numpyArray.sum()


import numpy as np
import pandas as pd

dataset = pd.read_csv('houses.csv')

dataset.head(20)

from sklearn.impute import SimpleImputer
imp = SimpleImputer(missing_values=np.nan, strategy='mean')
imp = imp.fit(dataset)
dataset = imp.transform(dataset)

X = dataset[:, :-1]
y = dataset[:, -1]

X
y

from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
X = sc.fit_transform(X)

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=42)

X_train
X_test
y_train
y_test

from sklearn.linear_model import SGDRegressor
 #clf = linear_model.SGDRegressor( penalty = 'l2' , max_iter=1000, tol=1e-3 , loss = 'huber')
sgd = SGDRegressor( penalty = 'l2' , max_iter=1000, tol=1e-3 , loss = 'squared_loss')
#clf = linear_model.SGDRegressor( penalty = 'l1' , max_iter=1000, tol=1e-3 , loss = 'huber')
#clf = linear_model.SGDRegressor( penalty = 'l1' , max_iter=1000, tol=1e-3 , loss = 'squared_loss')

sgd.fit(X_train, y_train)

y_pred = sgd.predict(X_test)
y_pred

sgd.score(X_train,y_train)
sgd.score(X_test,y_test)

from sklearn.metrics import mean_absolute_error
mean_absolute_error(y_test, y_pred)

from sklearn.metrics import mean_squared_error
mean_squared_error(y_test, y_pred)

Model Building/2.1 Linear Regression/2.1.4.4.py


"""
Generate collections of scattered points in Cartesian coordinates.
"""
import numpy as np

def scatter_circular(size, R1=3, R2=None, angle=0, reset_random=True):
    """
    Generate a collection of random points distributed in a circle or elipse.

    Parameters
    ----------
    size : int
        Number of points
    R1 : float
        Radius of the circle
    R2 : float
        If not the same as R1, then the output is an elipse
    angle : 0, float, optional
        Angle to rotate the coordinates of all the points, should be [0, 180)

    Returns
    -------
    2d array
        A collection of scattered points with the shape of 2xsize.
    """
    if reset_random:
        np.random.seed(0)

    _a = np.random.random_sample(size)
    _b = np.random.random_sample(size)

    points = np.zeros((2, size))
    for i in range(size):
        a = min(_a[i], _b[i])
        b = max(_a[i], _b[i])
        points[0, i] = b*R1*np.cos(2*np.pi*a/b)
        points[1, i] = b*R2*np.sin(2*np.pi*a/b)

    radian = angle/180*np.pi
    rotate_mat = np.array([[np.cos(radian), -np.sin(radian)], [np.sin(radian), np.cos(radian)]])
    points = rotate_mat @ points

    return points

def scatter_3D(size, **kwargs):
    """
    Generate a collection of random points in a 3-D Cartesian coordinate.

    Parameters
    ----------
    size : int
        Number of points

    Other Parameters
    ----------------
    **kwargs
        This method takes keyward arguments from ``scatter_circle``

    Returns
    -------
    2d array
        A collection of scattered points with the shape of 3xsize.
    """
    points = scatter_circular(size, **kwargs)
    _z = np.random.random_sample(size)

    return np.vstack((points, _z))


""""
Author : Aditya Jain
Contact : https://adityajain.me
"""
import numpy as np
import matplotlib.pyplot as plt

class SGDRegressor():
	"""
	SGD regressor model, that optimizes using gradient descent

	Parameters
	----------
	lr : float, learning rate (Default 0.01)

	tol : float, tolerance as stopping criteria for gradient descent (Default : 0.01)

	seed : integer, random seed

	normalize : boolean, normalize X in fit method

	Attributes
	----------
	coef_ : Estimated coefficients for the linear regression problem

	intercept_ : integer, bias for the linear regression problem

	"""
	def __init__(self, learning_rate=0.01, tol=0.01, seed=None,normalize=False):
		self.W = None
		self.b = None
		self.__lr = learning_rate
		self.__tol = tol
		self.__length = None
		self.__normalize = normalize
		self.__m = None
		self.__costs = []
		self.__iterations = []
		np.random.seed(seed if seed is not None else np.random.randint(100))

	def __initialize_weights_and_bais(self):
		self.W = np.random.randn(self.__length) #(n,1)
		self.b = 0

	def __computeCost(self,h,Y):
		loss = np.square(h-Y)
		cost = np.sum(loss)/(2*self.__m)
		return cost

	def __optimize(self,X,Y):
		h = np.dot(X,self.W)+self.b
		dW = np.dot( X.T, (h-Y) ) / self.__m
		db = np.sum( h-Y )  / self.__m
		self.W = self.W - self.__lr*dW
		self.b = self.b - self.__lr*db

	def __normalizeX(self,X): return (X-self.__mean) / (self.__std)

	def fit(self, X, y, verbose=False):
		"""
		Fit X using y by optimizing weights and bias

		Parameters
		----------
		X : 2D numpy array, independent variables

		y : 1D numpy array, dependent variable

		verbose : boolean, print out details while optimizing (Default : False)

		"""
		if self.__normalize:
			self.__mean, self.__std = X.mean(axis=0), X.std(axis=0)
			X = self.__normalizeX(X)
		self.__m,self.__length = X.shape
		self.__initialize_weights_and_bais()
		last_cost,i = float('inf'),0
		while True:
			h = np.dot(X,self.W)+self.b
			cost = self.__computeCost(h,y)
			if verbose: print(f"Iteration: {i}, Cost: {cost:.3f}")
			self.__optimize(X,y)
			if last_cost-cost < self.__tol: break
			else: last_cost,i = cost,i+1
			self.__costs.append(cost)
			self.__iterations.append(i)

	def predict(self,X):
		"""
		Predict dependent variable

		Parameters
		----------
		X : numpy array, independent variables

		Returns
		-------
		predicted values

		"""
		if self.__normalize: X = self.__normalizeX(X)
		return np.dot(X,self.W)+self.b

	def plot(self,figsize=(7,5)):
		"""
		Plot a optimization graph
		"""
		plt.figure(figsize=figsize)
		plt.plot(self.__iterations,self.__costs)
		plt.xlabel('Iterations')
		plt.ylabel('Cost')
		plt.title("Iterations vs Cost")
		plt.show()

	def score(self,X,y):
		"""
		Computer Coefficient of Determination (rsquare)

		Parameters
		----------
		X : 2D numpy array, independent variables

		y : numpy array, dependent variables

		Returns
		-------
		r2 values

		"""
		return 1-(np.sum(((y-self.predict(X))**2))/np.sum((y-np.mean(y))**2))

	@property
	def coef_(self): return self.W

	@property
	def intercept_(self): return self.b

class LinearRegression():
	"""
	An implementation of OLS regression

	Parameters
	----------
	normalize : boolean, normalize data use standardscaler before fitting

	Attributes
	----------
	coef_ : coefficients for each of the feature

	intercept_ : y intercept

	"""
	def __init__(self, normalize=False):
		self.__bias = None
		self.__normalize = normalize
		self.__weights = None
		self.__std = None
		self.__mean = None

	def __normalizeX(X):
		return (X-self.__mean)/self.__std

	def fit(self,X,y):
		"""
		Fit X,y into the model

		Parameters
		----------
		X : numpy array, array of independent variables
		y : numpy array, dependent variable

		"""
		if self.__normalize:
			self.__mean, self.__std = X.mean(axis=0), X.std(axis=0)
			X = self.__normalizeX(X)

		#weights = (X'X)^-1 X'Y
		self.__weights = np.dot( np.linalg.inv(np.dot(X.T, X)), np.dot( X.T, y ))
		self.__bias = y.mean() - np.sum(b * X.mean(axis=0))

	def predict(self,X):
		"""
		Predict dependent variable

		Parameters
		----------
		X : numpy array, independent variables

		Returns
		-------
		predicted values

		"""
		if self.__normalize:
			X = self.__normalizeX(X)
		return np.dot(X, self.__weights )+ self.__bias

	def score(self,X,y):
		"""
		Computer Coefficient of Determination (rsquare)

		Parameters
		----------
		X : 2D numpy array, independent variables

		y : numpy array, dependent variables

		Returns
		-------
		r2 values

		"""
		return 1-(np.sum(((y-self.predict(X))**2))/np.sum((y-np.mean(y))**2))

	@property
	def coef_(self): return self.__weights

	@property
	def intercept_(self): return self.__bias


"""
In this challenge, we're reinforcing what we've learned today.

Task
A bag contains 3 red marbles and 4 blue marbles. Then, 2 marbles are drawn from the bag, at random, without replacement.
If the first marble drawn is red, what is the probability that the second marble is blue?
"""

import numpy as np

def second_blue(N=10000):
    num_1red = 0
    num_1red_2blue = 0
    for i in range(N):
        # suppose 0-2 are red, 3-6 are blue
        # draw the first marble
        marble1 = np.random.randint(0, 7)

        # draw the second marble
        marble2 = np.random.randint(0, 7)
        # if the same, then redraw
        while marble2 == marble1:
            marble2 = np.random.randint(0, 7)

        if marble1<= 2:
            num_1red += 1
            if marble2 in range(3, 7):
                num_1red_2blue += 1

    # conditional probability
    return num_1red_2blue / num_1red


#!/usr/bin/env python

import numpy as np
from scipy.spatial.distance import pdist, squareform

### For matlab interface
# scipy.io.loadmat and scipy.io.savemat

# Create the following array where each row is a point in 2D space:
# [[0 1]
#  [1 0]
#  [2 0]]
x = np.array([[0, 1], [1, 0], [2, 0]])
print x

# Compute the Euclidean distance between all rows of x.
# d[i, j] is the Euclidean distance between x[i, :] and x[j, :],
# and d is the following array:
# [[ 0.          1.41421356  2.23606798]
#  [ 1.41421356  0.          1.        ]
#  [ 2.23606798  1.          0.        ]]
d = squareform(pdist(x, 'euclidean'))
print d


import numpy as np
from simple_markov_chain_lib import markov_chain

## Build Markov Chain
markov_table = {
    1: {2: 0.5, 3: 0.5},
    2: {1: 1/3, 4: 2/3},
    3: {3: 0.8, 4: 0.2},
    4: {1: 0.6, 4: 0.4}
}

for starting in [1,2,3,4]:
    init_dist = {starting: 1.0} #the chain starts from state 1 since we are interested in excursions around state 1.

    mc = markov_chain(markov_table, init_dist)

    N = 100_000

    ##Initialize the dictionary "visits". Every state is a key of this dictionary, with value 0
    visits = {state: 0 for state in (1, 2, 3, 4)}

    mc.start()
    completed = 0
    stoppingTimeCounter = 0
    stoppingTimes = []
    ##Simulate N excursions. Every time we complete an excursion we increase completed by 1.
    while completed < N:
        visits[mc.running_state] += 1
        mc.move()
        stoppingTimeCounter += 1
        if mc.running_state == starting:
            stoppingTimes.append(stoppingTimeCounter)
            stoppingTimeCounter = 0
            completed +=1

    print("Invariant Distribution starting from {}:".format(starting))
    for x, y in visits.items():
        print("%d: %.3f" % (x, (y / N)/np.mean(stoppingTimes)))


from scipy.stats import multivariate_normal
import numpy as np

def classification(X, mu, sigma, weight):
    k = len(weight)
    n = X.shape[0]
    X_pdf = np.zeros([k, n])
    for i in range(k):
        mu_k = mu[i]
        sigma_k = sigma[i]
        X_pdf[i] = weight[i] * multivariate_normal(mu_k, sigma_k).pdf(X)

    gamma = X_pdf / X_pdf.sum(axis=0)
    return np.argmax(gamma, axis=0)

def step_E(X, mu, sigma, weight):
    k = len(weight)
    n = X.shape[0]
    X_pdf = np.zeros([k, n])
    for i in range(k):
        mu_k = mu[i]
        sigma_k = sigma[i]
        X_pdf[i] = weight[i] * multivariate_normal(mu_k, sigma_k).pdf(X)
    return X_pdf

def step_M(X, X_pdf, mu, sigma, weight, t):
    k = len(weight)
    n = X.shape[0]
    verosimilitud = 0
    gamma = X_pdf / X_pdf.sum(axis=0)
    for i in range(k):
        sum_gamma_k = np.sum(gamma[i])
        weight[i] = sum_gamma_k / n

        mu[i] = np.sum(np.multiply(X.T, gamma[i]).T, axis=0) / sum_gamma_k

        sigma[i] = np.dot((X - mu[i]).T, np.multiply((X - mu[i]).T, gamma[i]).T) / sum_gamma_k
        verosimilitud += np.sum(np.log(weight[i] * np.sum(X_pdf[i])))
    return mu, sigma, weight, verosimilitud

def EM_algoritmo(X, mu, sigma, weight, t, t_max, epsilon, k, verosimilitud):
    n = X.shape[1]
    n_samples = X.shape[0]
    if t == 0:
        weight = np.repeat(1 / k, k)
        index = np.random.choice(np.linspace(0, n_samples, n_samples + 1), k, False)
        index = [int(i) for i in index]
        mu = X[index]
        sigma = np.full([k, n, n], np.cov(X, rowvar=False))

    X_pdf = step_E(X, mu, sigma, weight)
    mu, sigma, weight, verosimilitud_new = step_M(X, X_pdf, mu, sigma, weight, t)
    if (np.abs(verosimilitud_new - verosimilitud) > epsilon) & (t < t_max):
        t += 1
        return EM_algoritmo(X, mu, sigma, weight, t, t_max, epsilon, k, verosimilitud_new)
    else:
        print("Converge in iterations", t)
        return mu, sigma, weight, verosimilitud


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

#----------------------------------------------------------------------------
#   MÉTRICAS
#----------------------------------------------------------------------------

def AutoCov(X, k):
  n = len(X)
  mx = np.mean(X)
  c = np.zeros(n-k)
  for i in range(n - k):
    c[i] = (X[i] - mx)*(X[i+k] - mx)
  c = c.mean()

  return c

def CrossCov(X, Y, k):
  n = len(X)
  mx = np.mean(X)
  my = np.mean(Y)
  c = np.zeros(n-k)
  for i in range(n - k):
    c[i] = (X[i] - mx)*(Y[i+k] - my)
  c = c.mean()

  return c

def CCF(X, Y, k):
  gamma_xy = CrossCov(X, Y, k)
  gamma_x = Var(X)
  gamma_y = Var(Y)
  return gamma_xy / np.sqrt(gamma_x * gamma_y)

def plot_ccf(X, Y, k, **kwargs):
  ccf = []
  for i in range(k):
    ccf.append(CCF(X, Y,  i))

  ax = kwargs.get("axis", None)
  if ax is None:
    fig, ax = plt.subplots(nrows=1, ncols=1,figsize=[10,5])

  ax.hlines([0],[0],[k], color="black")
  ax.vlines([i for i in range(k)], [0 for i in range(k)], ccf, color="red")
  ax.scatter([i for i in range(k)], ccf, marker="*")
  ax.set_xlabel("k")
  ax.set_ylabel("CCF(k)")

#----------------------------------------------------------------------------
#   MODELOS COM VARIÁVEIS EXÓGENAS
#----------------------------------------------------------------------------

def lags_x(endog, exog, k):
  t = len(endog)
  n = len(exog)
  X = np.zeros((t-k, (n+1)*k))
  Y = endog[k:]
  for i in range(k, t):
    X[i-k,0:k] = endog[i-k:i]
    for e in range(n):
      X[i-k,(e+1)*k:(e+2)*k] = exog[e][i-k:i]
  return X,Y

def ajustar_arx(endog, exog, parametros):
  p = parametros[0]
  X,Y = lags_x(endog, exog, p)

  coef = np.linalg.inv(X.T @ X) @ (X.T @ Y )

  previsoes = arx(endog, exog, [coef, None])

  residuos = endog[p:] - previsoes

  sigma2 = np.std(residuos)

  return coef, sigma2

def arx(endog, exog, parametros):
  coef, _ = parametros
  t = len(endog)
  n = len(exog)
  p = int(len(coef) / (n+1))
  ret = np.zeros(t-p)
  X, _ = lags_x(endog, exog, p)
  for i in range(p,t):
    ret[i-p] = X[i-p].dot(coef)

  return ret

#----------------------------------------------------------------------------
#   MODELOS COM MULTIVARIADOS / VETORIAIS
#----------------------------------------------------------------------------

def lags_v(dados, p):
  T, n = dados.shape
  X = np.zeros((T-p, n*p))
  Y = dados[p:, :]
  for i in range(p, T):
    for j in range(p):
      X[i - p, j*n:(j*n)+n] = dados[i-(p-j), : ]
  return X, Y

def var(dados, parametros):
  T, n = dados.shape
  coef, _ = parametros
  p = int(coef.shape[0]/n)
  X,_ = lags_v(dados, p)
  ret = np.zeros((T-p, n))
  for i in range(T-p):
    ret[i, :] = coef.T @ X[i, :]
  return ret

def ajustar_var(dados, p):
  X,Y = lags_v(dados, p)

  coef = np.linalg.inv(X.T @ X) @ ( X.T @ Y )

  previsoes = var(dados, [coef, None])

  residuos = dados[p:, :] - previsoes

  Sigma = np.sqrt(np.cov(residuos, rowvar=False))

  return coef, Sigma


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

# exponential fn to fit to curves
def expfun(t, c1, a, T_inf):
    return - c1 * np.exp(-a * t) + T_inf

rawdata = pd.read_csv('lab2_home_raw_data.csv')

fig1, ax1 = plt.subplots(figsize=(7,3), tight_layout=True)
fig2, ax2 = plt.subplots(figsize=(7,3), tight_layout=True)

# we iterate through each type, of which
# there are two: (uninsulated, insulated)
curve_parameters = dict()
for runtype, d1 in rawdata.groupby('type'):
    xs = d1['time'][d1['time'] <= 50]
    ys = d1['tempK'][d1['time'] <= 50] - 273.15
    '''
    fit to our model of the system. For a body for which LC assumption is true, the governing
    equation is given by:

    dTs/dt = - (h As) / (m Cv) * ( T_s(t) - T_inf )

    We can group parameters:
    dTs/dt = - a * (Ts(t) - Tinf)

    This 1st order ode has solution of the form:
    where c1, a, and T_inf are free parameters

    T_s(t) = - c1 e^( -a t ) + T_inf

    So we fit the exp curve to those parameters
    '''
    params, _ = scipy.optimize.curve_fit(expfun, xs, ys, p0=(1, 1e-2, 1))
    xxs = np.linspace(np.min(xs), np.max(xs), 900)
    yys = expfun(xxs, *params)
    curve_parameters[runtype] = {
        'c1' : params[0],
        'hAs/mCv' : params[1],
        'T_inf' : params[2]
    }

    # we iterate through each run
    if runtype == 'uninsulated':
        for run, d2 in d1.groupby('video_fname'):
            ax1.scatter(d2['time'][d2['time'] <= 50], d2['tempK'][d2['time'] <= 50]- 273.15, marker='+', label=runtype)
        ax1.plot(xxs, yys, 'k', label='exp fitted - {}'.format(runtype))
        ax1.set_ylabel('Temperature (C)')
        ax1.set_xlabel('Time (s)')
        ax1.legend()

    elif runtype == 'insulated':
        for run, d2 in d1.groupby('video_fname'):
            ax2.scatter(d2['time'][d2['time'] <= 50], d2['tempK'][d2['time'] <= 50]- 273.15, marker='+', label=runtype)
        ax2.plot(xxs, yys, 'k', label='exp fitted - {}'.format(runtype))
        ax2.set_ylabel('Temperature (C)')
        ax2.set_xlabel('Time (s)')
        ax2.legend()

pd.DataFrame(curve_parameters).to_csv('table1.csv')
plt.show()


import numpy as np
from numpy import random
from collections import deque

def forward(A,B,pi,sequence,scale=False):
    N=A.shape[0]
    M=B.shape[1]
    T=len(sequence)
    alpha=np.zeros([T,N])
    alpha[0]=pi*B[:,sequence[0]]
    t=1
    while True:
        if t==T:
            break
        alpha[t]=alpha[t-1]@A*B[:,sequence[t]]
        if scale:
            alpha[t]/=np.sum(alpha[t])
        t+=1
    return(np.sum(alpha[T-1]),alpha)

def backward(A,B,pi,sequence,scale=False):
    N=A.shape[0]
    M=B.shape[1]
    T=len(sequence)
    beta=np.zeros([T,N])
    beta[T-1]=1
    t=T-2
    while True:
        if t<0:
            break
        beta[t]=A@(B[:,sequence[t+1]]*beta[t+1])
        if scale:
            beta[t]/=np.sum(beta[t])
        t-=1
    return(np.sum(pi*B[:,sequence[0]]*beta[0]),beta)

def Viterbi(A,B,pi,sequence):
    N=A.shape[0]
    M=B.shape[1]
    T=len(sequence)
    delta=np.zeros([T,N])
    psi=np.zeros([T,N])
    delta[0]=pi*B[:,sequence[0]]
    t=1
    while True:
        if t==T:
            break
        delta_A=delta[t-1,np.newaxis].T*A
        delta[t]=np.max(delta_A,axis=0)*B[:,sequence[t]]
        psi[t]=np.argmax(delta_A,axis=0)
        t+=1
    psi=psi.astype(int)
    q=np.zeros(T).astype(int)
    q[T-1]=np.argmax(delta[T-1])
    t=T-2
    while True:
        if t<0:
            break
        q[t]=psi[t+1,q[t+1]]
        t-=1
    return(q)

def Baum_Welch(A,B,pi,sequence,max_iter,threshold=1e-15,scale=False):
    N=A.shape[0]
    M=B.shape[1]
    T=len(sequence)
    likelihood,alpha=forward(A,B,pi,sequence,scale)
    for i in range(max_iter):
        beta=backward(A,B,pi,sequence,scale)[1]
        #temporary variables
        gamma=alpha*beta/np.sum(alpha*beta,axis=1).reshape((T,1))
        xi=np.zeros([N,N,T-1])
        for t in range(T-1):
            xi[:,:,t]=alpha[t].reshape((N,1))*A*beta[t+1]*B[:,sequence[t+1]]
            xi[:,:,t]=xi[:,:,t]/np.sum(xi[:,:,t])
        pi=gamma[0]
        A=np.sum(xi,axis=2)/np.sum(gamma[:-1],axis=0).reshape([N,1])
        B=np.zeros([N,M])
        for t in range(T):
            B[:,sequence[t]]+=gamma[t]
        B=B/np.sum(gamma,axis=0).reshape([N,1])
        likelihood_new,alpha=forward(A,B,pi,sequence,scale)
        if abs(likelihood-likelihood_new)<threshold:
            break
        likelihood=likelihood_new
    return(A,B,pi)

def Baum_Welch_linear_memory(A,B,pi,sequence,max_iter,threshold=1e-15):
    N=A.shape[0]
    M=B.shape[1]
    T=len(sequence)
    ###########################
    for z in range(max_iter):
        ##Beta_t+1
        beta_tilt_old=np.zeros(N)
        ##Beta_t
        beta_tilt_new=np.zeros(N)
        #T_t+1
        T_tilt_old=np.zeros([N,N,N])
        #T_t
        T_tilt_new=np.zeros([N,N,N])
        #E_t+1
        E_tilt_old=np.zeros([N,M,N])
        #E_t
        E_tilt_new=np.zeros([N,M,N])
        beta_tilt_old+=1
        d=1/np.sum(beta_tilt_old)
        beta_tilt_old=d*beta_tilt_old
        for m in range(N):
            for i in range(N):
                for gamma in range(M):
                    E_tilt_old[m,gamma,m]=beta_tilt_old[i]*int(sequence[T-1]==gamma)
        for t in range(T-2,-1,-1):
            beta_tilt_new=A@(B[:,sequence[t+1]]*beta_tilt_old)
            dt=1/np.sum(beta_tilt_new)
            for m in range(N):
                for i in range(N):
                    for j in range(N):
                        partial=0
                        for n in range(N):
                            partial+=A[m,n]*T_tilt_old[i,j,n]*B[n,sequence[t+1]]
                        T_tilt_new[i,j,m]=dt*(beta_tilt_old[j]*A[m,j]*B[j,sequence[t+1]]*int(i==m)+partial)
                    for gamma in range(M):
                        partial=0
                        for n in range(N):
                            partial+=B[n,sequence[t+1]]*A[m,n]*E_tilt_old[i,gamma,n]
                        E_tilt_new[i,gamma,m]=dt*(partial+beta_tilt_new[m]*int(sequence[t]==gamma)*int(m==i))
            beta_tilt_new=dt*beta_tilt_new
            beta_tilt_old=beta_tilt_new
            T_tilt_old=T_tilt_new
            E_tilt_old=E_tilt_new
        E_end=np.zeros([N,M])
        T_end=np.zeros([N,N])
        for m in range(N):
            E_end+=E_tilt_old[:,:,m]*pi[m]*B[m,sequence[0]]
            T_end+=T_tilt_old[:,:,m]*pi[m]*B[m,sequence[0]]
        alpha=pi*B[:,sequence[0]]
        pi=alpha*beta_tilt_old
        pi=pi/np.sum(pi)
        B=E_end/np.sum(E_end,axis=1).reshape((N,1))
        A=T_end/np.sum(T_end,axis=1).reshape((N,1))
    return(A,B,pi)

def Viterbi_linear_memory(A,B,pi,sequence):
    N=A.shape[0]
    M=B.shape[1]
    T=len(sequence)
    delta=np.zeros([T,N])
    psi=np.zeros([T,N])
    d = deque([], maxlen=T)
    delta[0]=pi*B[:,sequence[0]]
    t=1
    while True:
        if t==T:
            break
        delta_A=delta[t-1,np.newaxis].T*A
        delta[t]=np.max(delta_A,axis=0)*B[:,sequence[t]]
        d.append(np.argmax(delta_A,axis=0).astype(int))
        t+=1

    q=np.zeros(T).astype(int)
    q[T-1]=np.argmax(delta[T-1])

    t=T-2
    while d:
        q[t]=d.pop().reshape([N,1])[q[t+1]]
        t-=1
    return q

def sim_HMM(A,B,pi,length):
    states=np.arange(A.shape[0])
    outcomes=np.arange(B.shape[1])
    out_states=np.zeros(length)
    out_emission=np.zeros(length)
    out_states=np.zeros(length).astype(int)
    out_emission=np.zeros(length).astype(int)
    out_states[0]=random.choice(states,size=1,p=pi)
    out_emission[0]=random.choice(outcomes,size=1,p=B[out_states[0]])
    for i in range(1,length):
        out_states[i]=random.choice(states,size=1,p=A[out_states[i-1]])
        out_emission[i]=random.choice(outcomes,size=1,p=B[out_states[i]])
    return(out_states,out_emission)


import math
import numpy as np
import plotly.express as px
import plotly.graph_objects as go

# Relationship between power (kW) and Torque (Nm) with Motor Speed 2000 rpm
x = np.array([1.1, 1.5, 2.2, 3.7, 5.6])
y = np.array([5.3, 7.1, 10.7, 18, 27])

def gradient_descent(epochs, alpha):
    m = 0
    c = 0
    n = len(x)

    for _ in range(epochs):
        Y_pred = m*x + c

        D_m = (-2/n)*sum(x*(y - Y_pred))
        D_c = (-2/n)*sum(y - Y_pred)

        m = m - alpha * D_m
        c = c - alpha * D_c

    return [m, c]

def predict(x_train):
    [m, c] = gradient_descent(1000, 0.01)
    print('m = %.5f c = %.5f\n' % (m, c))
    Y_predict = m*x_train + c

    return Y_predict

def rmse(Y_predict):
    n = len(x)
    substract = []
    squared_error = []

    for i in range(n):
        subs = Y_predict[i] - y[i]
        substract.append(subs)
        square = pow(substract[i], 2)
        squared_error.append(square)

    rmse = math.sqrt(sum(squared_error) / n)

    return rmse

y_prediction = predict(x)
y_prediction = np.round(y_prediction, 3)

print('Prediction = %s\n' % (y_prediction))
print('RMSE = %s' % (rmse(y_prediction)))

fig1 = px.scatter(x=x, y=y, color_discrete_sequence=['green'])
fig = go.Figure(data=fig1.data)
fig.add_trace(go.Scatter(x=x, y=y_prediction, name='Linear Regression'))
fig.show()


import numpy as np
from math import sqrt

def distance(x1, y1, x2, y2):
    '''
    Distance between two points (x1, y1), (x2, y2).
    '''
    return pow((pow(x1 - x2, 2) + pow(y1 - y2, 2)), 0.5)

def node_dist(node1, node2):
    '''
    Distance between two nodes.
    '''
    return distance(node1.x, node1.y, node2.x, node2.y)

def edge_dist(A, B, E):
    '''
    Distance from Node E to edge A->B. Adapted from GeeksforGeeks.
    '''
    A = [A.x, A.y]
    B = [B.x, B.y]
    E = [E.x, E.y]
    # vector AB
    AB = [None, None];
    AB[0] = B[0] - A[0];
    AB[1] = B[1] - A[1];

    # vector BP
    BE = [None, None];
    BE[0] = E[0] - B[0];
    BE[1] = E[1] - B[1];

    # vector AP
    AE = [None, None];
    AE[0] = E[0] - A[0];
    AE[1] = E[1] - A[1];

    # Variables to store dot product

    # Calculating the dot product
    AB_BE = AB[0] * BE[0] + AB[1] * BE[1];
    AB_AE = AB[0] * AE[0] + AB[1] * AE[1];

    # Minimum distance from
    # point E to the line segment
    reqAns = 0;

    # Case 1
    if (AB_BE > 0) :

        # Finding the magnitude
        y = E[1] - B[1];
        x = E[0] - B[0];
        reqAns = sqrt(x * x + y * y);

    # Case 2
    elif (AB_AE < 0) :
        y = E[1] - A[1];
        x = E[0] - A[0];
        reqAns = sqrt(x * x + y * y);

    # Case 3
    else:

        # Finding the perpendicular distance
        x1 = AB[0];
        y1 = AB[1];
        x2 = AE[0];
        y2 = AE[1];
        mod = sqrt(x1 * x1 + y1 * y1);
        reqAns = abs(x1 * y2 - y1 * x2) / mod;

    return reqAns


import numpy as np

from functools import partial
from lab1.src.generators.quadratic_form_generator import generate_matrix_with_condition_number

def generate_function_by_quadratic_matrix(m):
    def foo(x):
        return sum(m[i][j] * x[i] * x[j] for i in range(len(m)) for j in range(len(m)))

    return foo

def generate_grad_by_quadratic_matrix(m):
    def grad_component(i, x):
        return sum(np.array(m[i]) * np.array(x) * [2 if j == i else 1 for j in range(len(m))])

    def grad(x):
        return np.array([grad_component(i, x) for i in range(len(m))])

    return grad

def generate_optimization_task(n: int, k: float):
    matrix = generate_matrix_with_condition_number(n, k)
    f = generate_function_by_quadratic_matrix(matrix)
    f_grad = generate_grad_by_quadratic_matrix(matrix)
    return f, f_grad


import numpy as np

def mdape(y_actual, y_pred):
    # median absolute percentage error
    return np.median(np.abs((y_actual - y_pred) / y_actual)) * 100


# Native

# Site-packages
import numpy as np

# Locals

def MSE(y_true: np.array, y_pred: np.array) -> float:
    return np.round(((y_true - y_pred)**2).mean(), 5)

def MAE(y_true: np.array, y_pred: np.array) -> float:
    return np.round((np.abs(y_true - y_pred)).mean(), 5)

def RMSE(y_true: np.array, y_pred: np.array) -> float:
    return np.round(MSE(y_true, y_pred)**0.5, 5)

def logLoss(y_true: np.array, y_pred: np.array) -> float:
    pred = (y_pred * (1 - 2 * 1e-15)) + 1e-15
    return np.round(-((y_true * np.log(pred)) + ((1 - y_true) * np.log(1 - pred))).mean(axis=0), 5)

def hingeLoss(y_true, y_pred):
    return np.round(np.clip(1 - y_true * y_pred, 0, float('inf')).mean(axis=0), 5)


import numpy as np
from scipy import constants
import matplotlib as mpl
import matplotlib.ticker
import matplotlib.pyplot as plt
import sys

re = 6371E3;

def distance(phi_l_deg, h):
    phi_l_rad = phi_l_deg * np.pi / 180.0;
    return np.sqrt((re * np.sin(phi_l_rad))**2 + 2 * re * h + h**2) - re * np.sin(phi_l_rad)

def fsl(d, f):
    c = constants.speed_of_light
    return 20.0 * np.log10( 4 * np.pi * f * d / c )

def elevation_angle_to_earth_angle(elevation_angle: float, orbit_height: float):
    elevation_angle = elevation_angle * np.pi / 180
    return 180 / np.pi * (np.arccos(re / (re + orbit_height) * np.cos(elevation_angle)) - elevation_angle)

if __name__ == "__main__":

    plt.close()

    h = 650E3;
    a = np.linspace(90, 0, 19);
    z = distance(a, h);

    if(len(sys.argv) >= 3):
        elevation_angle = int(sys.argv[1])
        f               = int(sys.argv[2])
        print(fsl(10**3 * distance(elevation_angle, h), 10**9 * f))
        exit()

    fig, ax = plt.subplots(1)
    ax.plot(a, z / 1e3, 'rx')
    ax.invert_xaxis()
    ax.xaxis.set_major_locator(matplotlib.ticker.MultipleLocator(base = 10.0))

    ax.grid(True, which = 'major')
    ax.grid(True, which = 'minor', axis = 'y')
    ax.minorticks_on()

    plt.title   ("Distance between satellite and base station")
    plt.xlabel  ("Elevation angle $\phi_l$ [deg]")
    plt.ylabel  ("Distance [km]")

    plt.savefig ("../output/distance.svg")
    plt.savefig ("../output/distance.png")

    plt.show()

    fig, ax = plt.subplots(1)
    losses = fsl(z, 7.8E9)
    ax.plot(a, losses, 'rx')
    ax.invert_xaxis()
    ax.xaxis.set_major_locator(matplotlib.ticker.MultipleLocator(base = 10.0))

    ax.grid(True, which = 'major')
    ax.grid(True, which = 'minor', axis = 'y')
    ax.minorticks_on()

    plt.title   ("Free space losses")
    plt.xlabel  ("Elevation angle $\phi_l$ [deg]")
    plt.ylabel  ("FSL [dB]")

    plt.savefig ("../output/fsl.svg")
    plt.savefig ("../output/fsl.png")

    plt.show()


# -*- coding: utf-8 -*-
"""
Created on Mon Feb 15 11:37:30 2021
Simulate SIR Model:
    Where
    S — The number of people who are susceptible to the disease
    I — The number of people infected with the disease
    R — Those incapable of infecting others; either recovered or diseased
@author: ROY.ZHOU
"""

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

# Total population, N.
N = 1000
# Initial number of infected and recovered individuals, I0 and R0.
I0, R0 = 1, 0
# Everyone else, S0, is susceptible to infection initially.
S0 = N - I0 - R0
# Contact rate, beta, and mean recovery rate, gamma, (in 1/days).
beta, gamma = 0.2, 1./10
# A grid of time points (in days)
t = np.linspace(0, 160, 160)

# The SIR model differential equations
def deriv(y, t, N, beta, gamma):
    S, I, R = y
    dSdt = -beta * S * I / N
    dIdt = beta * S * I / N - gamma * I
    dRdt = gamma * I
    return dSdt, dIdt, dRdt

# Initial conditions vector
y0 = S0, I0, R0
# Integrate the SIR equations over the time grid, t.
ret = odeint(deriv, y0, t, args=(N, beta, gamma))
S, I, R = ret.T

# Plot the data on three separate curves for S(t), I(t) and R(t)
fig = plt.figure(facecolor='w')
ax = fig.add_subplot(111, facecolor='#dddddd', axisbelow=True)
ax.plot(t, S/1000, 'b', alpha=0.5, lw=2, label='S')
ax.plot(t, I/1000, 'r', alpha=0.5, lw=2, label='I')
ax.plot(t, R/1000, 'g', alpha=0.5, lw=2, label='R')
ax.set_xlabel('Time / days')
ax.set_ylabel('Number (1000s)')
ax.set_ylim(0,1.2)
ax.yaxis.set_tick_params(length=0)
ax.xaxis.set_tick_params(length=0)
legend = ax.legend()
legend.get_frame().set_alpha(0.6)
for spine in ('top', 'right', 'bottom', 'left'):
    ax.spines[spine].set_visible(False)
plt.show()


import numpy as np
import sympy as sp
from scipy.misc import derivative
from scipy import stats

def errorprop(f, variables, values, errors):
    """Propagate errors"""
    returnvals = f.subs([(var, val) for var, val in zip(variables, values)])
    derivsum = sum([sp.Derivative(f, var)**2 * err**2 for var, err in zip(variables, errors)])
    prop = sp.sqrt(derivsum).doit().subs([(var, val) for var, val in zip(variables, values)])
    return np.float64(sp.N(returnvals)), np.float64(sp.N(prop))

def errorprop2(f, values, errors):
    value = f(*values)
    som = 0
    for i in range(0, len(values)):
        deriv = derivative(lambda x: f(*values[0:i], x, *values[i+1:len(values)]), values[i])
        som += (deriv**2 * errors[i]**2)
    error = np.sqrt(som)
    return (value, error)

def chi2(x, y, dy, model, parameters):
    """Geeft least-squares waarde terug"""
    errors = ((y - model(x, *parameters))**2) / dy**2
    return np.sum(errors)

def weighted_average(waardenlijst, foutenlijst):
    """Geeft gewogen gemiddelde en de bijhorende fout"""
    gewichtenlijst = []
    for fout in foutenlijst:
        gewichtenlijst.append(1 / (fout**2))
    fout_op_gemiddelde = 1 / np.sqrt(sum(gewichtenlijst))

    tellerlijst = []
    for i in range(len(waardenlijst)):
        tellerlijst.append(gewichtenlijst[i]*waardenlijst[i])

    teller = sum (tellerlijst)
    noemer = sum (gewichtenlijst)

    gewogen_gemiddelde = teller / noemer
    # print("Het gewogen gemiddelde is ", gewogen_gemiddelde, "+-", fout_op_gemiddelde)
    return gewogen_gemiddelde, fout_op_gemiddelde

def test_compatibiliteit(x, sx, y, sy, alpha=None):
    """Test compatibiliteit van twee waarden"""
    fout = np.sqrt(sx**2 + sy**2)
    z = np.abs(x-y) / fout
    p = 2*(1 - stats.norm.cdf(z))
    print("z-value is:  ", str(round(z, 3)))
    print("p-value is:  ", str(round(p, 3)), " = ", str(round(p*100,1)),"%")
    if alpha:
        if p < alpha:
            print("REJECT at alpha = {}".format(alpha))
        else:
            print("NOT REJECTED at alpha = {}".format(alpha))
    else:
        if p < 0.05:
            print("REJECT at alpha = 0.05")
        if p < 0.01:
            print("REJECT at alpha = 0.01")

    return z, p


#!/usr/bin/env python
# Demonstrate criterion of Chauvenet to exclude poor data
# Use data example from Bevington & Robinson

from numpy.random import normal
from scipy.special import erf, erfc
import numpy
from kapteyn import kmpfit
from matplotlib.pyplot import figure, show, rc

def chauvenet(x, y, mean=None, stdv=None):
   #-----------------------------------------------------------
   # Input:  NumPy arrays x, y that represent measured data
   #         A single value of a mean can be entered or a
   #         sequence of means with the same length as
   #         the arrays x and y. In the latter case, the
   #         mean could be a model with best-fit parameters.
   # Output: It returns a boolean array as filter.
   #         The False values correspond to the array elements
   #         that should be excluded
   #
   # First standardize the distances to the mean value
   # d = abs(y-mean)/stdv so that this distance is in terms
   # of the standard deviation.
   # Then the  CDF of the normal distr. is given by
   # phi = 1/2+1/2*erf(d/sqrt(2))
   # Note that we want the CDF from -inf to -d and from d to +inf.
   # Note also erf(-d) = -erf(d).
   # Then the threshold probability = 1-erf(d/sqrt(2))
   # Note, the complementary error function erfc(d) = 1-erf(d)
   # So the threshold probability pt = erfc(d/sqrt(2))
   # If d becomes bigger, this probability becomes smaller.
   # If this probability (to obtain a deviation from the mean)
   # becomes smaller than 1/(2N) than we reject the data point
   # as valid. In this function we return an array with booleans
   # to set the accepted values.
   #
   # use of filter:
   # xf = x[filter]; yf = y[filter]
   # xr = x[~filter]; yr = y[~filter]
   # xf, yf are cleaned versions of x and y and with the valid entries
   # xr, yr are the rejected values from array x and y
   #-----------------------------------------------------------
   if mean is None:
      mean = y.mean()           # Mean of incoming array y
   if stdv is None:
      stdv = y.std()            # Its standard deviation
   N = len(y)                   # Lenght of incoming arrays
   criterion = 1.0/(2*N)        # Chauvenet's criterion
   d = abs(y-mean)/stdv         # Distance of a value to mean in stdv's
   d /= 2.0**0.5                # The left and right tail threshold values
   prob = erfc(d)               # Area normal dist.
   filter = prob >= criterion   # The 'accept' filter array with booleans
   return filter                # Use boolean array outside this function

def residuals(p, data):
   a, b = p
   x, y, err = data
   return (y-a-b*x)/err

def prob( Xlo, Xhi ):
   sq2 = numpy.sqrt(2.0)
   # Left tail and right tail area
   return 1.0 - 0.5 * (erf(Xhi/sq2) - erf(Xlo/sq2))

# Artificial data
x = numpy.array([2, 4, 6, 8, 10, 12])
y = numpy.array([3.5, 7.2, 9.5, 17.1, 20.0, 25.5])
err = numpy.array([0.55, 0.65, 0.74, 0.5, 0.85, 0.6])

# Prepare plot
fig = figure()
rc('legend', fontsize=8)
frame = fig.add_subplot(1,1,1)
frame.plot(x, y, 'go', label="data")
frame.set_xlabel("x")
frame.set_ylabel("y")
frame.set_title("Exclude poor data with criterion of Chauvenet")

params0 = (1,1)
fitter = kmpfit.Fitter(residuals=residuals, data=(x,y,err))
fitter.fit(params0=params0)

print("======== Fit results all data included ==========")
print("Params:                      ", fitter.params)
print("Uncertainties:               ", fitter.xerror)
print("Errors assuming red.chi^2=1: ", fitter.stderr)
print("Iterations:                  ", fitter.niter)
print("Function ev:                 ", fitter.nfev)
print("dof:                         ", fitter.dof)
print("chi^2, rchi2:                ", fitter.chi2_min, fitter.rchi2_min)
print("Status:                      ", fitter.status)

from scipy.stats import chi2
rv = chi2(fitter.dof)
print("If H0 was correct, then")
print("the probability to find a chi-squared higher than this:  ", 1-rv.cdf(fitter.chi2_min))
print("If we set the threshold to alpha=0.05, we REJECT H0.")

a, b = fitter.params
N = len(y)
mean = a + b*x
stdv = err
criterion = 1.0/(2*N)
print("\nExclude loop:")
for xf, yf, m, std in zip(x, y, mean, stdv):
   d = abs(yf-m)/std
   P = prob(-d, d)
   if P < criterion:
      print("Data y=%f has distance %fsigma to mean (%f), prob.=%f" %(yf,d,m,P))
      print("Based on Chauvenet's criterion (prob=%g), we reject data point y=%g"\
      %(criterion,yf))
      frame.plot((xf,), (yf,), 'rx', ms=20)

# The function chauvenet() does it the NumPy way
filter = chauvenet(x, y, mean, stdv)
xf = x[filter]; yf = y[filter]; errf = err[filter]
xe = x[~filter]; ye = y[~filter]; erre = err[~filter]
print("Excluded by function chauvenet() are:")
print(list(zip(xe, ye)))
fitter = kmpfit.Fitter(residuals=residuals, data=(xf,yf,errf))
fitter.fit(params0=params0)

print("\n======== Fit results with filtered data ==========")
print("Params:                      ", fitter.params)
print("Uncertainties:               ", fitter.xerror)
print("Errors assuming red.chi^2=1: ", fitter.stderr)
print("Iterations:                  ", fitter.niter)
print("Function ev:                 ", fitter.nfev)
print("dof:                         ", fitter.dof)
print("chi^2, rchi2:                ", fitter.chi2_min, fitter.rchi2_min)
print("Status:                      ", fitter.status)

rv = chi2(fitter.dof)
print("If H0 was correct, then")
print("the probability to find a chi-squared higher than this:  ", 1-rv.cdf(fitter.chi2_min))
print("If we set the threshold to alpha=0.05, we ACCEPT H0.")

frame.set_ylim(0, 1.1*y.max())
frame.errorbar(xf, yf, errf, fmt='go')
frame.errorbar(xe, ye, erre, fmt='ro')
frame.plot(x, a+b*x, 'g', label="Fit unfilterd data")
a, b = fitter.params
frame.plot(x, a+b*x, 'b', label="Fit filterd data")
leg = frame.legend(loc=2)
show()


# -*- coding: utf-8 -*-
"""2D functions."""
import numpy as np

def angle(origin, pt):
    """
    compute angle between the vector from origin to pt and the x-direction vector.

    For example:

    .. doctest::

        >>> angle((0,0), (1,1)) # should return pi/4
        0.7853981633974484
    """
    x1, y1 = (1, 0)
    x2, y2 = (pt[0] - origin[0], pt[1] - origin[1])
    inner_product = x1 * x2 + y1 * y2
    len1 = np.hypot(x1, y1)
    len2 = np.hypot(x2, y2)
    if y2 < 0:
        return 2 * np.pi - np.arccos(inner_product / (len1 * len2))
    else:
        return np.arccos(inner_product / (len1 * len2))

if __name__ == "__main__":
    import doctest
    doctest.testmod()


import numpy as np

def softmax(predictions):
    """
    Computes probabilities from scores

    Arguments:
      predictions, np array, shape is either (N) or (batch_size, N) -
        classifier output

    Returns:
      probs, np array of the same shape as predictions -
        probability for every class, 0..1
    """
    axis = predictions.ndim - 1
    stab = (predictions.T - np.max(predictions, axis=axis)).T
    exps = np.exp(stab)
    return (exps.T / exps.sum(axis=axis)).T

def cross_entropy_loss(probs, target_index):
    """
    Computes cross-entropy loss

    Arguments:
      probs, np array, shape is either (N) or (batch_size, N) -
        probabilities for every class
      target_index: np array of int, shape is (1) or (batch_size) -
        index of the true class for given sample(s)

    Returns:
      loss: single value
    """
    if probs.ndim == 1:
        idx = target_index
    else:
        idx = (np.arange(probs.shape[0]), target_index)
    return -np.mean(np.log(probs[idx]))

def softmax_with_cross_entropy(predictions, target_index):
    """
    Computes softmax and cross-entropy loss for model predictions,
    including the gradient

    Arguments:
      predictions, np array, shape is either (N) or (batch_size, N) -
        classifier output
      target_index: np array of int, shape is (1) or (batch_size) -
        index of the true class for given sample(s)

    Returns:
      loss, single value - cross-entropy loss
      dprediction, np array same shape as predictions - gradient of predictions by loss value
    """
    probs = softmax(predictions)
    loss = cross_entropy_loss(probs, target_index)

    if probs.ndim == 1:
        n_batches = 1
        idx = target_index
    else:
        n_batches = probs.shape[0]
        idx = (np.arange(n_batches), target_index)

    dprediction = probs
    dprediction[idx] -= 1
    dprediction /= n_batches

    return loss, dprediction

def l2_regularization(W, reg_strength):
    """
    Computes L2 regularization loss on weights and its gradient

    Arguments:
      W, np array - weights
      reg_strength - float value

    Returns:
      loss, single value - l2 regularization loss
      gradient, np.array same shape as W - gradient of weight by l2 loss
    """
    loss = reg_strength * (W ** 2).sum()
    grad = 2 * reg_strength * W
    return loss, grad

def linear_softmax(X, W, target_index):
    """
    Performs linear classification and returns loss and gradient over W

    Arguments:
      X, np array, shape (num_batch, num_features) - batch of images
      W, np array, shape (num_features, classes) - weights
      target_index, np array, shape (num_batch) - index of target classes

    Returns:
      loss, single value - cross-entropy loss
      gradient, np.array same shape as W - gradient of weight by loss

    """
    predictions = X.dot(W)
    loss, dprediction = softmax_with_cross_entropy(predictions, target_index)
    dW = X.T.dot(dprediction)
    return loss, dW

class LinearSoftmaxClassifier:
    def __init__(self):
        self.W = None

    def fit(self, X, y, batch_size=100, learning_rate=1e-7, reg=1e-5,
            epochs=1):
        """
        Trains linear classifier

        Arguments:
          X, np array (num_samples, num_features) - training data
          y, np array of int (num_samples) - labels
          batch_size, int - batch size to use
          learning_rate, float - learning rate for gradient descent
          reg, float - L2 regularization strength
          epochs, int - number of epochs
        """

        num_train = X.shape[0]
        num_features = X.shape[1]
        num_classes = np.max(y) + 1
        if self.W is None:
            self.W = 0.001 * np.random.randn(num_features, num_classes)

        loss_history = []
        for epoch in range(epochs):
            loss = None
            shuffled_indices = np.arange(num_train)
            np.random.shuffle(shuffled_indices)
            sections = np.arange(batch_size, num_train, batch_size)
            batches_indices = np.array_split(shuffled_indices, sections)

            for batch in batches_indices:
                ce_loss, ce_grad = linear_softmax(X[batch], self.W, y[batch])
                reg_loss, reg_grad = l2_regularization(self.W, reg)
                loss, grad = ce_loss + reg_loss, ce_grad + reg_grad
                self.W -= learning_rate * grad
                loss_history.append(loss)

            print("Epoch %i, loss: %f" % (epoch, loss))

        return loss_history

    def predict(self, X):
        """
        Produces classifier predictions on the set

        Arguments:
          X, np array (test_samples, num_features)

        Returns:
          y_pred, np.array of int (test_samples)
        """
        return X.dot(self.W).argmax(axis=1)


"""
Copyright 2013 Steven Diamond

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""

# for decimal division
from __future__ import division

import cvxopt
import numpy as np
from pylab import *
import math

from cvxpy import *

# Taken from CVX website http://cvxr.com/cvx/examples/
# Example: CVX Textbook exercise 4.3: Solve a simple QP with inequality constraints
# Ported from cvx matlab to cvxpy by Misrab Faizullah-Khan
# Original comments below

# From Boyd & Vandenberghe, "Convex Optimization"
# Joelle Skaf - 09/26/05
#
# Solves the following QP with inequality constraints:
#           minimize    1/2x'*P*x + q'*x + r
#               s.t.    -1 <= x_i <= 1      for i = 1,2,3
# Also shows that the given x_star is indeed optimal

# Generate data
n = 3
P = cvxopt.matrix([	13, 12, -2,
					12, 17, 6,
					-2, 6, 12], (n,n))
q = cvxopt.matrix([-22, -14.5, 13], (n,1))
r = 1
x_star = cvxopt.matrix([1, 1/2, -1], (n,1))

# Frame and solve the problem

x = Variable(n)
objective = Minimize(  0.5 * quad_form(x, P)  + q.T * x + r )
constraints = [ x >= -1, x <= 1]

p = Problem(objective, constraints)
# The optimal objective is returned by p.solve().
result = p.solve()


import numpy as np

def calculate_q(p_seq):
  """
  Benjamini-Hochberg method
  """
  p_arr          = np.array(p_seq)
  n_genes        = len(p_arr)
  sort_index_arr = np.argsort(p_arr)
  p_sorted_arr   = p_arr[sort_index_arr]
  q_arr          = p_sorted_arr * n_genes / (np.arange(n_genes) + 1)
  q_min          = q_arr[-1]
  q_list         = [q_min]
  for q in q_arr[-2::-1]:
    if q < q_min:
      q_min = q
    q_list.append(q_min)
  q_arr = np.array(q_list)[::-1]
  q_arr[sort_index_arr] = q_arr.copy()
  return q_arr

if __name__ == '__main__':
  p_arr = np.random.rand(5)
  q_arr = calculate_q(p_arr)
  print('p-values', p_arr)
  print('q-values', q_arr)


import math

import numpy as np
import torch

from core.gaze_utils import average_angle, get_yaw_pitch

def test_get_yaw_pitch():
    assert np.linalg.norm(np.array([math.pi / 2, 0]) - get_yaw_pitch(np.array([1, 0, 0])).numpy()) < 1e-5
    assert np.linalg.norm(np.array([-math.pi / 2, 0]) - get_yaw_pitch(np.array([-1, 0, 0])).numpy()) < 1e-5
    assert np.linalg.norm(
        np.array([0, math.pi / 4]) - get_yaw_pitch(np.array([0, 1 / math.sqrt(2), -1 / math.sqrt(2)])).numpy()) < 1e-5
    assert np.linalg.norm(np.array([math.pi, 0]) - get_yaw_pitch(np.array([0, 0, 1])).numpy()) < 1e-5

def test_average_angle():
    p = math.pi
    a = torch.Tensor([0, p / 4, p / 2, p - 0.01, p - 0.03])
    b = torch.Tensor([-p / 4, -p / 4, -3 * p / 4, -p + 0.03, -p + 0.01])

    avg = average_angle(a, b)
    expected = torch.Tensor([-p / 8, 0, 7 * p / 8, -p + 0.01, p - 0.01])
    assert torch.max(torch.abs(avg - expected)).item() < 1e-6


import numpy as np
import pygenome as pg

def onemax(vector):
    '''
    Onemax fitness function

    Args:
        vector (array): binary array

    Returns:
        sum of ones in the binary array
    '''
    return np.sum(vector)

def sphere_model(vector):
    '''
    Sphere Model fitness function

    Args:
        vector (array): float array

    Returns:
        computed solution
    '''
    sphere = np.vectorize(lambda x : x ** 2.0)

    return np.sum(sphere(vector))


from __future__ import division
from sympy import *
from timeit import Timer
import mpmath
import math
import matplotlib.pyplot as plt

x, y, z, t = symbols('x y z t')
COEF_ADAMS_BASH = [
    [1],
    [1],
    [3/2, -1/2],
    [23/12, -4/3, 5/12],
    [55/24, -59/24, 37/24, -3/8],
    [1901/720, -1387/360, 109/30, -637/360, 251/720],
    [4277/1440, -2641/480, 4991/720, -3649/720, 959/480, -95/288],
    [198721/60480, -18637/2520, 235183/20160, -10754/945, 135713/20160, -5603/2520, 19087/60480],
    [16083/4480, -1152169/120960, 242653/13440, -296053/13440, 2102243/120960, -115747/13440, 32863/13440, -5257/17280]
]
COEF_ADAM_MOULTON = [
    [1],
    [1],
    [1/2, 1/2],
    [5/12, 2/3, -1/12],
    [3/8, 19/24, -5/24, 1/24],
    [251/720, 323/360, -11/30, 53/360, -19/720],
    [95/288, 1427/1440, -133/240, 241/720, -173/1440, 3/160],
    [19087/60480, 2713/2520, -15487/20160, 586/945, -6737/20160, 263/2520, -863/60480],
    [5257/17280, 139849/120960, -4511/4480, 123133/120960, -88547/120960, 1537/4480, -11351/120960, 275/24192]
]
COEF_FORM_INV = [
    [1],
    [1, 1],
    [2/3, 4/3, -1/3],
    [6/11, 18/11, -9/11, 2/11],
    [12/25, 48/25, -36/25, 16/25, -3/25],
    [60/137, 300/137, -300/137, 200/137, -75/137, 12/137],
    [60/147, 360/147, -450/147, 400/147, -225/147, 72/147, -10/147]
]

SHOW_GRAPHS = True ## MUDAR PARA TRUE CASO DESEJE VER OS GRAFICOS!
BY_LISTA_VALORES = 0
BY_EULER = 1
BY_EULER_INVERSO = 2
BY_EULER_APRIMORADO = 3
BY_RUNGE_KUTTA = 4

def F(f, t0, y0):
    return f.subs({t : t0, y : y0})

def f_bashforth(funcao, valores_iniciais, passo_atual, h, t0, ordem):
    retorno = valores_iniciais[passo_atual - 1]
    k = int(0)

    for i in range(passo_atual - 1, passo_atual - ordem - 1, -1):
        fn = F(funcao, t0 + i * h, valores_iniciais[i])
        retorno += h * (fn * COEF_ADAMS_BASH[ordem][k])
        k += 1

    return retorno

def f_moulton(funcao, valores_iniciais, passo_atual, h, t0, ordem):
    retorno = valores_iniciais[passo_atual - 1]
    k = int(0)

    for i in range(passo_atual, passo_atual - ordem, -1):
        fn = F(funcao, t0 + i * h, valores_iniciais[i])
        retorno += h * (fn * COEF_ADAM_MOULTON[ordem][k])
        k += 1

    return retorno

def f_inversa(funcao, valores_iniciais, passo_atual, h, t0, ordem):
    y1 = valores_iniciais[passo_atual]
    t1 = t0 + (passo_atual) * h
    retorno = COEF_FORM_INV[ordem][0] * h * F(funcao, t1, y1)
    k = 1

    for i in range(passo_atual - 1, passo_atual - ordem - 1, -1):
        yn = valores_iniciais[i]
        retorno += (yn * COEF_FORM_INV[ordem][k])
        k += 1

    return retorno

def print_header(nome_metodo, y0, t0, h):
    print('Metodo de ' + nome_metodo)
    print('y(' + str(t0) + ') = ' + str(y0))
    print('h = ' + str(h))

def mostra_grafico(nome_metodo, tempos, resultados):
    if (SHOW_GRAPHS == 0):
        return

    plt.title('Metodo ' + nome_metodo)
    plt.plot(tempos, resultados)
    plt.show()

def euler_simples(y0, t0, h, qtd_passos, funcao, flag):
    if (flag == 0):
        print_header('Euler Simples', y0, t0, h)

    qtd_passos = int(qtd_passos)
    y0 = float(y0)
    t0 = float(t0)
    h = float(h)
    f = sympify(funcao)

    resultados = []
    tempos = []

    if (flag == 0):
        print('0 ' + str(y0))

    resultados.append(y0)
    tempos.append(t0)

    for passo_atual in range(1, qtd_passos + 1):
        ft0y0 = F(f, t0, y0)
        y1 = y0 + ft0y0 * h
        t1 = t0 + h
        if (flag == 0):
            print(str(passo_atual) + ' ' + str(y1))
        y0 = y1
        t0 = t1
        resultados.append(y0)
        tempos.append(t0)

    if (flag == 0):
        mostra_grafico('Euler Simples', tempos, resultados)

    return resultados

def euler_inverso(y0, t0, h, qtd_passos, funcao, flag):
    if (flag == 0):
        print_header('Euler Inverso', y0, t0, h)

    qtd_passos = int(qtd_passos)
    y0 = float(y0)
    t0 = float(t0)
    h = float(h)
    f = sympify(funcao)

    resultados = []
    tempos = []

    if (flag == 0):
        print('0 ' + str(y0))

    resultados.append(y0)
    tempos.append(t0)

    for passo_atual in range(1, qtd_passos + 1):
        y1 = y0 + F(f, t0, y0) * h
        t1 = t0 + h
        y1 = y0 + (h * F(f, t1, y1))
        # eq = y0 + (h * F(f, t0 + h, y)) (resolucao implicita)
        # eq = y - eq
        # y1 = solve(eq, y).pop()
        if (flag == 0):
            print(str(passo_atual) + ' ' + str(y1))
        y0 = y1
        t0 = t1
        resultados.append(y0)
        tempos.append(t0)

    if (flag == 0):
        mostra_grafico('Euler Inverso', tempos, resultados)

    return resultados

def euler_aprimorado(y0, t0, h, qtd_passos, funcao, flag):
    if (flag == 0):
        print_header('Euler Aprimorado', y0, t0, h)

    resultados = []
    tempos = []

    qtd_passos = int(qtd_passos)
    y0 = float(y0)
    t0 = float(t0)
    h = float(h)
    f = sympify(funcao)

    if (flag == 0):
        print('0 ' + str(y0))

    resultados.append(y0)
    tempos.append(t0)

    for passo_atual in range(1, qtd_passos + 1):
        ft0y0 = F(f, t0, y0)
        y1 = y0 + ft0y0 * h
        t1 = t0 + h
        ft1y1 = F(f, t1, y1)

        y1 = y0 + ((ft0y0 + ft1y1) * (h)) / 2.0

        if (flag == 0):
            print(str(passo_atual) + ' ' + str(y1))

        y0 = y1
        t0 = t1
        resultados.append(y0)
        tempos.append(t0)

    if (flag == 0):
        mostra_grafico('Euler Aprimorado', tempos, resultados)

    return resultados

def runge_kutta(y0, t0, h, qtd_passos, funcao, flag):
    if (flag == 0):
        print_header('Runge-Kutta', y0, t0, h)

    resultados = []
    tempos = []

    qtd_passos = int(qtd_passos)
    y0 = float(y0)
    t0 = float(t0)
    h = float(h)
    f = sympify(funcao)

    if (flag == 0):
        print('0 ' + str(y0))

    resultados.append(y0)
    tempos.append(t0)

    for passo_atual in range (1, qtd_passos + 1):
        k1 = F(f, t0, y0)
        k2 = F(f, t0 + h / 2.0, y0 + (h * k1) / 2.0)
        k3 = F(f, t0 + h / 2.0, y0 + (h * k2) / 2.0)
        k4 = F(f, t0 + h, y0 + h * k3)

        y1 = y0 + (h / 6.0) * (k1 + 2 * k2 + 2.0 * k3 + k4)

        if (flag == 0):
            print(str(passo_atual) + ' ' + str(y1))

        y0 = y1
        t0 = t0 + h
        resultados.append(y0)
        tempos.append(t0)

    if (flag == 0):
        mostra_grafico('Runge-Kutta', tempos, resultados)

    return resultados

def adams_bashforth(entrada, t0, h, qtd_passos, funcao, ordem, origem):
    resultados = []
    tempos = []

    qtd_passos = int(qtd_passos)
    t0 = float(t0)
    h = float(h)
    f = sympify(funcao)
    ordem = int(ordem)
    origem = int(origem)

    valores_iniciais = []
    nome_metodo = ""

    if (origem == BY_LISTA_VALORES):
        valores_iniciais = entrada
        nome_metodo = 'Adams-Bashforth'
    elif (origem == BY_EULER):
        valores_iniciais = euler_simples(entrada, t0, h, ordem - 1, funcao, 1)
        nome_metodo = 'Adams-Bashforth por Euler Simples'
    elif (origem == BY_EULER_INVERSO):
        valores_iniciais = euler_inverso(entrada, t0, h, ordem - 1, funcao, 1)
        nome_metodo = 'Adams-Bashforth por Euler Inverso'
    elif (origem == BY_EULER_APRIMORADO):
        valores_iniciais = euler_aprimorado(entrada, t0, h, ordem - 1, funcao, 1)
        nome_metodo = 'Adams-Bashforth por Euler Aprimorado'
    elif (origem == BY_RUNGE_KUTTA):
        valores_iniciais = runge_kutta(entrada, t0, h, ordem - 1, funcao, 1)
        nome_metodo = 'Adams-Bashforth por Runge-Kutta (ordem = ' + str(ordem) + ')'

    print_header(nome_metodo, valores_iniciais[0], t0, h)

    for i in range(ordem):
        valores_iniciais[i] = float(valores_iniciais[i])
        print(str(i) + ' ' + str(valores_iniciais[i]))
        resultados.append(valores_iniciais[i])
        tempos.append(float(t0 + i * h))

    for passo_atual in range(ordem, qtd_passos + 1):
        y1 = f_bashforth(f, valores_iniciais, passo_atual, h, t0, ordem)
        print(str(passo_atual) + ' ' + str(y1))
        valores_iniciais.append(y1)
        resultados.append(y1)
        tempos.append(t0 + passo_atual * h)

    mostra_grafico(nome_metodo, tempos, resultados)

    return resultados

def adam_moulton(y0, t0, h, qtd_passos, funcao, ordem, origem):
    resultados = []
    tempos = []

    qtd_passos = int(qtd_passos)
    t0 = float(t0)
    h = float(h)
    f = sympify(funcao)
    ordem = int(ordem)

    valores_iniciais = []
    nome_metodo = ""

    if (origem == BY_LISTA_VALORES):
        valores_iniciais = y0
        nome_metodo = 'Adam-Moulton'
    elif (origem == BY_EULER):
        valores_iniciais = euler_simples(y0, t0, h, ordem - 2, funcao, 1)
        nome_metodo = 'Adam-Moulton por Euler Simples'
    elif (origem == BY_EULER_INVERSO):
        valores_iniciais = euler_inverso(y0, t0, h, ordem - 2, funcao, 1)
        nome_metodo = 'Adam-Moulton por Euler Inverso'
    elif (origem == BY_EULER_APRIMORADO):
        valores_iniciais = euler_aprimorado(y0, t0, h, ordem - 2, funcao, 1)
        nome_metodo = 'Adam-Moulton por Euler Aprimorado'
    elif (origem == BY_RUNGE_KUTTA):
        valores_iniciais = runge_kutta(y0, t0, h, ordem - 2, funcao, 1)
        nome_metodo = 'Adam-Moulton por Runge-Kutta (ordem = ' + str(ordem) + ')'

    print_header(nome_metodo, valores_iniciais[0], t0, h)

    for i in range(ordem - 1):
        valores_iniciais[i] = float(valores_iniciais[i])
        print(str(i) + ' ' + str(valores_iniciais[i]))
        resultados.append(valores_iniciais[i])
        tempos.append(t0 + i * h)

    for passo_atual in range(ordem - 1, qtd_passos + 1):
        y1 = f_bashforth(f, valores_iniciais, passo_atual, h, t0, ordem - 1) #previsao a partir de a. bash.
        valores_iniciais.append(y1)
        y1 = f_moulton(f, valores_iniciais, passo_atual, h, t0, ordem)
        valores_iniciais.pop()
        print(str(passo_atual) + ' ' + str(y1))
        valores_iniciais.append(float(y1))
        resultados.append(y1)
        tempos.append(t0 + passo_atual * h)

    mostra_grafico(nome_metodo, tempos, resultados)

    return resultados

def formula_inversa(y0, t0, h, qtd_passos, funcao, ordem, origem):
    resultados = []
    tempos = []

    qtd_passos = int(qtd_passos)
    t0 = float(t0)
    h = float(h)
    f = sympify(funcao)
    ordem = int(ordem)

    valores_iniciais = []
    nome_metodo = ""

    if (origem == BY_LISTA_VALORES):
        valores_iniciais = y0
        nome_metodo = 'Formula Inversa de Dif.'
    elif (origem == BY_EULER):
        valores_iniciais = euler_simples(y0, t0, h, ordem - 2, funcao, 1)
        nome_metodo = 'Formula Inversa de Dif. por Euler Simples'
    elif (origem == BY_EULER_INVERSO):
        valores_iniciais = euler_inverso(y0, t0, h, ordem - 2, funcao, 1)
        nome_metodo = 'Formula Inversa de Dif. por Euler Inverso'
    elif (origem == BY_EULER_APRIMORADO):
        valores_iniciais = euler_aprimorado(y0, t0, h, ordem - 2, funcao, 1)
        nome_metodo = 'Formula Inversa de Dif. por Euler Aprimorado'
    elif (origem == BY_RUNGE_KUTTA):
        valores_iniciais = runge_kutta(y0, t0, h, ordem - 2, funcao, 1)
        nome_metodo = 'Formula Inversa de Dif. por Runge-Kutta (ordem = ' + str(ordem) + ')'

    print_header(nome_metodo, valores_iniciais[0], t0, h)

    for i in range(ordem - 1):
        valores_iniciais[i] = float(valores_iniciais[i])
        print(str(i) + ' ' + str(valores_iniciais[i]))
        resultados.append(valores_iniciais[i])
        tempos.append(t0 + i * h)

    for passo_atual in range(ordem - 1, qtd_passos + 1):
        y1 = f_bashforth(f, valores_iniciais, passo_atual, h, t0, ordem - 1) #previsao a partir de a. bash.
        valores_iniciais.append(y1)
        y1 = f_inversa(f, valores_iniciais, passo_atual, h, t0, ordem - 1)
        valores_iniciais.pop()
        print(str(passo_atual) + ' ' + str(y1))
        valores_iniciais.append(float(y1))
        resultados.append(y1)
        tempos.append(t0 + passo_atual * h)

    mostra_grafico(nome_metodo, tempos, resultados)

    return resultados

def filtra_entrada(data):
    metodo = data[0]
    euler = metodo.find('euler') != -1
    rk = metodo.find('runge_kutta') != -1
    bashforth = metodo.find('bashforth') != -1
    multon = metodo.find('multon') != -1
    by = metodo.find('by') != -1
    inversa = metodo.find('formula') != -1

    valores_iniciais = []
    ordem = -1

    if (not by and not euler and not rk):
        if (multon or inversa):
            ordem = int(data[len(data) - 1])
            valores_iniciais = []
            for valor in range(1, ordem):
                valores_iniciais.append(data[valor])
        else:
            ordem = int(data[len(data) - 1])
            valores_iniciais = []
            for valor in range(1, ordem + 1):
                valores_iniciais.append(data[valor])

    if (bashforth):
        if (not by):
            return (valores_iniciais, data[ordem + 1], data[ordem + 2], data[ordem + 3], data[ordem + 4], ordem)
        else:
            return (data[1], data[2], data[3], data[4], data[5], data[6])
    elif (multon):
        if (not by):
            return (valores_iniciais, data[ordem], data[ordem + 1], data[ordem + 2], data[ordem + 3], ordem)
        else:
            return (data[1], data[2], data[3], data[4], data[5], data[6])
    elif (inversa):
        if (not by):
            return (valores_iniciais, data[ordem], data[ordem + 1], data[ordem + 2], data[ordem + 3], ordem)
        else:
            return (data[1], data[2], data[3], data[4], data[5], data[6])
    elif (euler):
        return (data[1], data[2], data[3], data[4], data[5], -1)
    elif (rk):
        return (data[1], data[2], data[3], data[4], data[5], -1)
    else:
        print('Metodo nao existente.')

    return (-1, -1, -1, -1, -1, -1)

def calcula_origem(nome_metodo):
    euler_inv = nome_metodo.find('by_euler_inverso')
    euler_apr = nome_metodo.find('by_euler_aprimorado')
    euler_simp = nome_metodo.find('by_euler')
    rk = nome_metodo.find('by_runge_kutta')

    if (euler_inv != -1):
        return BY_EULER_INVERSO
    elif (euler_apr != -1):
        return BY_EULER_APRIMORADO
    elif (euler_simp != -1):
        return BY_EULER
    elif (rk != -1):
        return BY_RUNGE_KUTTA
    else:
        return BY_LISTA_VALORES

def main():
    input_file = open('entrada.txt', 'r')

    tempos_metodos = []

    for line in input_file:
        data = line.split(' ')

        y0, t0, h, qtd_passos, funcao, ordem = filtra_entrada(data)

        metodo = data[0]
        tempo = 0

        if (metodo == "euler"):
            t = Timer(lambda : euler_simples(y0, t0, h, qtd_passos, funcao, 0))
            tempo = t.timeit(number=1)
        elif (metodo == "euler_inverso"):
            t = Timer(lambda : euler_inverso(y0, t0, h, qtd_passos, funcao, 0))
            tempo = t.timeit(number=1)
        elif (metodo == "euler_aprimorado"):
            t = Timer(lambda : euler_aprimorado(y0, t0, h, qtd_passos, funcao, 0))
            tempo = t.timeit(number=1)
        elif (metodo == "runge_kutta"):
            t = Timer(lambda : runge_kutta(y0, t0, h, qtd_passos, funcao, 0))
            tempo = t.timeit(number=1)
        elif (metodo.find('bashforth') != -1):
            origem = calcula_origem(metodo)
            t = Timer(lambda : adams_bashforth(y0, t0, h, qtd_passos, funcao, ordem, origem))
            tempo = t.timeit(number=1)
        elif (metodo.find('multon') != -1):
            origem = calcula_origem(metodo)
            t = Timer(lambda : adam_moulton(y0, t0, h, qtd_passos, funcao, ordem, origem))
            tempo = t.timeit(number=1)
        else:
            origem = calcula_origem(metodo)
            t = Timer(lambda : formula_inversa(y0, t0, h, qtd_passos, funcao, ordem, origem))
            tempo = t.timeit(number=1)

        print('')
        tempos_metodos.append((metodo, tempo))

    # DESCOMENTAR P/ MOSTRAR O TEMPO DE EXECUÇÃO DE CADA MÉTODO
    # for tempo in tempos_metodos:
    #     print(tempo)
    #     print('---')

if __name__ == "__main__":
    main()


# Refer: https://en.wikipedia.org/wiki/Test_functions_for_optimization

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

pso_solver.setSeed(1)

lower = xlower = ylower = -4
upper = xupper = yupper = 4
particleList = pso_solver.createRandomParticleList(2, numParticles=10, lower=lower, upper=upper)

# Testing on Himmelblau's function
# This function has 4 global minima, which minimum is computed by PSO depends on the initialization.
# seed = 1 gives minimum (-2.81, 3.13)
# seed = 2 gives minimum (-3, 2)
# seed = 3 gives mimimum (3.58, -1.85)
# seed = 4 gives mimimum (3, 2)
f = lambda x, y: (x**2 + y - 11)**2 + (x + y**2 - 7)**2

pso_solver.psoVisualizeBivariate(particleList, f, xlower, xupper, ylower, yupper, c1=1, c2=1, W=0.5, numIters=50, maxFlag=False, sleepTime=0.1, density=1000, accuracy=2, verbose=False)


# -*- coding: utf-8 -*-
"""
Created on Sat Jan  6 06:17:43 2018

@author: Alankar
"""

import numpy as np

M_sun = 1.989e30 #in kg
G = 6.67e-11

def ecc(vmax,rmin):
    e = (vmax**2*rmin)/(G*M_sun)-1
    return e

def apph(e,vmax,rmin):
    c = (vmax*rmin)**2/(G*M_sun)
    rmax = c/(1-e)
    return rmax

def v_app(vmax,rmin,rmax):
    vmin = (vmax*rmin)/rmax
    return vmin

def time_p(vmax,rmin,e):
    c = (vmax*rmin)**2/(G*M_sun)
    a = c/(1-e**2)
    T = np.sqrt((((2*np.pi)**2)/(G*M_sun))*a**3)
    return T/(365*24*60**2) #in yr

print('-----------------------------------------------------------')
print('Demo Output:\n\nEarth')
vmax, rmin = 3.0287e4, 1.4710e11
e = ecc(vmax,rmin)
rmax = apph(e,vmax,rmin)
vmin = v_app(vmax,rmin,rmax)
T = time_p(vmax,rmin,e)
#1 m = 6.685e-12 AU
print('\nOrbital Eccentricity: %.4f\nAphelion Distance(m): %.3e\nAphelion Velocity(m/s): %.3e\nOrbital period(yr): %.2f'%(e,rmax,vmin,T))
print('\nHalley\'s Comet')
vmax, rmin = 5.4529e4, 8.7830e10
e = ecc(vmax,rmin)
rmax = apph(e,vmax,rmin)
vmin = v_app(vmax,rmin,rmax)
T = time_p(vmax,rmin,e)
print('\nOrbital Eccentricity: %.4f\nAphelion Distance(m): %.3e\nAphelion Velocity(m/s): %.3e\nOrbital period(yr): %.2f'%(e,rmax,vmin,T))
print('-----------------------------------------------------------')

vmax = float(input('Enter velocity at perihelion(m/s): '))
rmin = float(input('Enter distance from Sun at perihelion(m): '))
e = ecc(vmax,rmin)
rmax = apph(e,vmax,rmin)
vmin = v_app(vmax,rmin,rmax)
T = time_p(vmax,rmin,e)
print('\nOrbital Eccentricity: %.4f\nAphelion Distance(m): %.3e\nAphelion Velocity(m/s): %.3e\nOrbital period(yrs): %.2f'%(e,rmax,vmin,T))


from src.si.supervised.Model import Model
from ..util.metrics import mse
from ..util.util import add_intersect
import numpy as np

class LinearRegression(Model):

    def __init__(self, gd=False, epochs=1000, lr=0.001):
        super(LinearRegression, self).__init__()
        self.gd = gd
        self.theta = None
        self.epochs = epochs
        self.lr = lr

    def fit(self, dataset):
        X, Y = dataset.getXy()#vai buscar X e y do dataset
        X = np.hstack((np.ones((X.shape[0], 1)), X))
        self.X = X
        self.Y = Y

        # closed form of GD
        self.train_gd(X, Y) if self.gd else self.train_closed(X, Y)
        self.is_fitted = True

    def train_closed(self, x, y):
        self.theta = np.linalg.inv(x.T.dot(x)).dot(x.T).dot(y)

    def train_gd(self, x, y):
        m = x.shape[0]
        n = x.shape[1]

        self.history = {}  # criar um historico dos thetas e custo por epoch
        self.theta = np.zeros(n)

        for epoch in range(self.epochs):
            grad = 1/m * (x.dot(self.theta) - y).dot(x)
            self.theta -= self.lr * grad

            self.history[epoch] = [self.theta[:], self.cost()]

    def predict(self, x):
        assert self.is_fitted, 'Model must be fitted before predicting'
        x = np.array(x)
        if x.ndim > 1:#ndim: numero de dimensoes
            res = []
            for i in x:
                _x = np.hstack(([1], i))
                res.append(np.dot(self.theta, _x))
        else:
            _x = np.hstack(([1], x))
            res = np.dot(self.theta, _x)
        return res

    def cost(self, X=None, Y=None, theta=None):
        X = add_intersect(X) if X is not None else self.X
        Y = Y if Y is not None else self.Y
        theta = theta if theta is not None else self.theta

        y_pred = np.dot(X, theta)
        return mse(Y, y_pred) / 2

class LinearRegressionReg(LinearRegression):

    def __init__(self, gd=False, epochs=1000, lr=0.001, lbd=1):
        super(LinearRegressionReg, self).__init__(gd=gd, epochs=epochs, lr=lr)
        self.lbd = lbd

    def train_closed(self, x, y):
        n = x.shape[1]
        identity = np.eye(n)
        identity[0, 0] = 0
        self.theta = np.linalg.inv(x.T.dot(x) + self.lbd * identity).dot(x.T).dot(y)
        self.is_fitted = True

    def train_gd(self, x, y):
        m = x.shape[0]
        n = x.shape[1]

        self.history = {}  # criar um historico dos thetas por epoch
        self.theta = np.zeros(n)
        lbds = np.full(m, self.lbd)
        lbds[0] = 0

        for epoch in range(self.epochs):
            grad = 1 / m * (x.dot(self.theta) - y).dot(x)
            self.theta -= (self.lr/m) * (lbds+grad)

            self.history[epoch] = [self.theta[:], self.cost()]


import numpy as np

# Part 1-2

number_of_samples = np.int(1e6)
gauss_data = np.random.normal(0,1,number_of_samples)
samples_greater_than_three = 0
for i in gauss_data:
    if i>3:
        samples_greater_than_three+=1
fraction_of_samples = samples_greater_than_three/number_of_samples

print('\nPart 1,2 x~G(0,1)\nnumber of x>3 samples: %i\nfraction of samples: %f\nhypothesis rejected %i times' \
      %(samples_greater_than_three,fraction_of_samples, samples_greater_than_three))

# Part 3

# (1)
number_of_samples = np.int(1e6)
gauss_data = np.random.normal(0,np.sqrt(2),number_of_samples)
samples_greater_than_three = 0
for i in gauss_data:
    if i>3:
        samples_greater_than_three+=1
fraction_of_samples = samples_greater_than_three/number_of_samples

print('\nPart 3.1 x~G(0,2)\nnumber of x>3 samples: %i\nfraction of samples: %f\nhypothesis rejected %i times' \
      %(samples_greater_than_three,fraction_of_samples, samples_greater_than_three))

# (2)
gauss_data_m_equals_two = np.random.normal(-0.5,1,number_of_samples)
samples_greater_than_three = 0
for i in gauss_data_m_equals_two:
    if i>3:
        samples_greater_than_three+=1
fraction_of_samples = samples_greater_than_three/number_of_samples

print('\nPart 3.2 x~G(-0.5,1)\nnumber of x>3 samples: %i\nfraction of samples: %f\nhypothesis rejected %i times' \
      %(samples_greater_than_three,fraction_of_samples, samples_greater_than_three))


#!/usr/bin/env python2
# -*- coding: utf-8 -*-
"""
       _
      /  |     | __  _ __  _
     /   |    /  |_||_|| ||
    /    |   /   |  |\ | ||_
   /____ |__/\ . |  | \|_|\_|
   __________________________ .

Created on Tue Jun 12 10:18:09 2018

@author: chrisunderwood
"""

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

class select_Gaus_fit():
    def __init__(self, x, y, plottingOnOff, guess):
        self.x = x
        self.y = y
        self.plotting = plottingOnOff
        self.guess = guess
        if self.plotting:
            self.plotInput()

        self.fit_gaus_2_to_8()

    def gaus2(self, x, *params):
        #Gaussian function
        A = params[0]
        x0 = params[1]
        c = params[2]
        return A*np.exp(-((x-x0)/(c**2))**2)

    def gaus4(self, x, *params):
        #Gaussian function
        A = params[0]
        x0 = params[1]
        c = params[2]
        return A*np.exp(-((self.x-x0)/(c**2))**4)

    def gaus6(self, x, *params):
        #Gaussian function
        A = params[0]
        x0 = params[1]
        c = params[2]
        return A*np.exp(-((self.x-x0)/(c**2))**6)

    def gaus8(self, x, *params):
        #Gaussian function
        A = params[0]
        x0 = params[1]
        c = params[2]
        return A*np.exp(-((self.x-x0)/(c**2))**8)

    def plotInput(self):
        plt.plot(self.x,self.y)

    def fitGaus2(self):
        self.popt_G2, self.pcov_G2 = curve_fit(self.gaus2, self.x, self.y ,
                                               p0=self.guess)
        self.fitG2 = self.gaus2(self.x, *self.popt_G2)

        if self.plotting:
            print 'Fitting SG2: '
            print self.guess
            print self.popt_G2
            print
            plt.plot(self.x, self.fitG2)

    def fitGaus4(self):
        self.popt_G4, self.pcov_G4 = curve_fit(self.gaus4, self.x, self.y ,
                                               p0=self.guess)
        self.fitG4 = self.gaus4(self.x, *self.popt_G4)
        if self.plotting:
            print 'Fitting SG4: '
            print self.guess
            print self.popt_G4
            print
            plt.plot(self.x, self.fitG4)

    def fitGaus6(self):
        self.popt_G6, self.pcov_G6 = curve_fit(self.gaus6, self.x, self.y ,
                                               p0=self.guess)
        self.fitG6 = self.gaus6(self.x, *self.popt_G6)
        if self.plotting:
            print 'Fitting SG6: '
            print self.guess
            print self.popt_G6
            print
            plt.plot(self.x, self.fitG6)

    def fitGaus8(self):

        self.popt_G8, self.pcov_G8 = curve_fit(self.gaus8, self.x, self.y ,
                                               p0=self.guess)
        self.fitG8 = self.gaus8(self.x, *self.popt_G8)
        if self.plotting:
            print 'Fitting SG8: '
            print self.guess
            print self.popt_G8
            print
            plt.plot(self.x, self.fitG8)

    def fit_gaus_2_to_8(self):
        self.fitOptions = ['SG2', 'SG4', 'SG6', 'SG8']
        self.fitPowers = [2, 4, 6, 8]

        self.fitGaus2()
        self.fitGaus4()
        self.fitGaus6()
        self.fitGaus8()
        self.fitParams = [self.popt_G2, self.popt_G4, self.popt_G6, self.popt_G8]
        self.CalcR_2_value()

    def nearposn(self, array,value):
        posn = (abs(array-value)).argmin()
        return posn

    def CalcR_2_value(self):
        self.rrValues = []
        for fit in [self.fitG2, self.fitG4, self.fitG6, self.fitG8]:

            residuals = self.y - fit
            ss_res = np.sum(residuals**2)
            ss_tot = np.sum((self.y-np.mean(self.y))**2)
            self.rrValues.append( 1 - (ss_res / ss_tot) )
        maxRR = max(self.rrValues)
        self.bestFit = self.nearposn(self.rrValues, maxRR)
        outStr = ''
        CSI="\x1B[31;40m"
        CEND = '\x1B[0m'
        for i in self.rrValues:
            if i == self.rrValues[self.bestFit]:
                outStr += CSI + str(i) + ' ' + CEND
            else:
                outStr += str(i) + ' '
        if self.plotting: print outStr

    def output(self):
        if self.plotting:
            print self.fitOptions[self.bestFit]
            print self.fitParams[self.bestFit]
            print self.fitPowers[self.bestFit]
        return self.fitPowers[self.bestFit] , self.fitParams[self.bestFit]


"""
Collection of functions to compute various performance measures from a 2x2 confusion matrix.
As an introduction to evaluating classificators, we recommend reading this `paper`_ about ROC analysis.

TP = true positive

FP = false positive

TN = true negative

FN = false negative

.. _paper: http://dx.doi.org/10.1016/j.patrec.2005.10.010.
"""

import numpy as np
from math import sqrt

def mcc(TP, FN, FP, TN):
    """Matthews Correlation Coefficient"""
    return np.divide(
        TP * TN + FP * FN, sqrt((TP + FP) * (TP + FN) * (TN + FP) * (TN + FN))
    )

def sens(TP, FN, FP, TN):
    """Sensitivity"""
    return np.divide(TP, (TP + FN))

def spec(TP, FN, FP, TN):
    """Specificity"""
    return np.divide(TN, (TN + FP))

def prec_pos(TP, FN, FP, TN):
    """Posivitve Precision"""
    return np.divide(TP, (TP + FP))

def recall_pos(TP, FN, FP, TN):
    """Positive recall"""
    return np.divide(TP, (TP + FN))

def prec_neg(TP, FN, FP, TN):
    """Negative Precision"""
    return np.divide(TN, (TN + FN))

def recall_neg(TP, FN, FP, TN):
    """Negative recall"""
    return np.divide(TN, (TN + FP))

def f1_pos(TP, FN, FP, TN):
    """f1-measure on positive instances"""
    return np.divide(
        2 * prec_pos(TP, FN, FP, TN) * recall_pos(TP, FN, FP, TN),
        (prec_pos(TP, FN, FP, TN) + recall_pos(TP, FN, FP, TN)),
    )

def f1_neg(TP, FN, FP, TN):
    """f1-measure on negative instances."""
    return np.divide(
        2 * prec_neg(TP, FN, FP, TN) * recall_neg(TP, FN, FP, TN),
        (prec_neg(TP, FN, FP, TN) + recall_neg(TP, FN, FP, TN)),
    )


from __future__ import annotations

from typing import Generator
from sympy import I, Basic
from sympy.core.backend import zeros, sqrt

from ._base import LieGroup
from ..algebras import A

def generalized_gell_mann(dimension: int) -> Generator:
    """Generator of generalized Gell-Mann Matrices. Note order may
    be different than usual because we generate symmetric, then antisymmetric,
    then diagonal.

    Args:
        dimension (int): Dimension of group

    Yields:
        Generator[Matrix]: Python Generator of (mathematical) generators

    Sources:
        - https://mathworld.wolfram.com/GeneralizedGell-MannMatrix.html

    """
    def eij(dim):
        def _(i, j):
            mat = zeros(dim)
            mat[i, j] = 1
            return mat
        return _
    E = eij(dimension)

    # Symmetric
    for k in range(dimension):
        for j in range(k):
            yield E(k, j) + E(j, k)

    # AntiSymmetric
    for k in range(dimension):
        for j in range(k):
            yield I * (E(k, j) - E(j, k))

    # Diagonal
    for l in range(dimension - 1):
        coeff = sqrt(2) / sqrt((l+1) * (l + 2))
        sum_term = sum([E(j, j) for j in range(l+1)], zeros(dimension))
        yield coeff * (sum_term - (l+1) * E(l+1, l+1))

class SU(LieGroup):
    """The Special Unitary Group
    """

    def __new__(cls, dim: int):
        if dim < 2:
            raise NotImplementedError("SU(1)==U(1) is not implemented yet.")
        return super().__new__(cls, "SU", dim)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._algebra = A(self.dimension - 1)
        self._generators = None

    def generators(self):
        r"""Generators for SU(N).  Based off the generalized Gell-Mann matrices $\lambda_a$
        the generators, $T_a$ are

        .. math::

            T_a = \frac{\lambda_a}{2}
        """
        if self._generators is None:
            # typical normalization
            self._generators = [
                x / 2 for x in generalized_gell_mann(self.dimension)]
        return self._generators


# -*- coding: utf-8 -*-
"""
helper function: convert Hz to Bark scale

  Args:
    fInHz: The frequency to be converted, can be scalar or vector
    cModel: The name of the model ('Schroeder' [default], 'Terhardt', 'Zwicker', 'Traunmuller')

  Returns:
    Bark values of the input dimension
"""

import numpy as np
import math

def ToolFreq2Bark(fInHz, cModel = 'Schroeder'):
    def acaSchroeder_scalar(f):
        return 7 * math.asinh(f/650)
    def acaTerhardt_scalar(f):
        return 13.3 * math.atan(0.75 * f/1000)
    def acaZwicker_scalar(f):
        return 13 * math.atan(0.76 * f/1000) + 3.5 * math.atan(f/7500)
    def acaTraunmuller_scalar(f):
        return 26.81/(1+1960./f) - 0.53

    f = np.asarray(fInHz)
    if f.ndim == 0:
        if cModel == 'Terhardt':
            return acaTerhardt_scalar(f)
        elif cModel == 'Zwicker':
            return acaZwicker_scalar(f)
        elif cModel == 'Traunmuller':
            return acaTraunmuller_scalar(f)
        else:
            return acaSchroeder_scalar(f)

    fBark = np.zeros(f.shape)
    if cModel == 'Terhardt':
        for k,fi in enumerate(f):
            fBark[k] =  acaTerhardt_scalar(fi)
    elif cModel == 'Zwicker':
        for k,fi in enumerate(f):
            fBark[k] =  acaZwicker_scalar(fi)
    elif cModel == 'Traunmuller':
        for k,fi in enumerate(f):
            fBark[k] =  acaTraunmuller_scalar(fi)
    else:
        for k,fi in enumerate(f):
            fBark[k] =  acaSchroeder_scalar(fi)

    return (fBark)


import numpy as np
from . import transform

class circle:
	"""This class defines an object of type circle.
	Attributes:
		center: (0,0) by default.
		radius: 1 by default.
		"""

	def __init__(self, radius=1, center=(0,0),pts=100,text_tag='Circle'):
		self.text_tag = text_tag
		self.r = radius
		self.xc , self.yc = center
		self.perimeter = 2*np.pi*self.r
		self.area = np.pi*self.r**2
		self.theta = np.linspace(0,2*np.pi,pts)
		self.x = self.r*np.cos(self.theta) + self.xc
		self.y = self.r*np.sin(self.theta) + self.yc

		return

	def plot(self,ax_f,linewidth=2,text_tag=None):
		if text_tag is None:
			ax_f.plot(self.x,self.y,linewidth=2,label=self.text_tag)
		else:
			ax_f.plot(self.x,self.y,linewidth=2,label=text_tag)

class ellipse:
	"""This class defines an object of type ellipse.
	Attributes:
		center: (0,0) by default.
		(major_axis,minor_axis): (1,2) by default.
		"""

	def __init__(self, maj_mi_tuple = (1,2), center=(0,0),pts=100,text_tag='Ellipse'):

		self.text_tag = text_tag
		self.major_axis, self.minor_axis = maj_mi_tuple
		self.xc , self.yc = center
		self.perimeter = np.pi*(self.major_axis + self.minor_axis)

		#self.area = np.pi*self.major_axis*self.minor_axis
		self.theta = np.linspace(0,2*np.pi,pts)
		self.x = self.major_axis*np.cos(self.theta) + self.xc
		self.y = self.minor_axis*np.sin(self.theta) + self.yc

	def rotate(self,theta):
		#print('rotate by theta', theta)
		x_rot, y_rot = transform.rotate(self.x-self.xc,self.y-self.yc,theta)

		self.x = x_rot + self.xc
		self.y = y_rot + self.yc

	def rotate(self,theta):
		x_rot, y_rot = transform.rotate(self.x-self.xc,self.y-self.yc,theta)
		self.x = x_rot + self.xc
		self.y = y_rot + self.yc

	def rotate_about_center(self,theta):
		x_rot, y_rot = transform.rotate(self.x,self.y,theta)
		self.xc, self.yc = transform.rotate(self.xc,self.yc,theta)
		self.x = x_rot
		self.y = y_rot

	def plot(self,ax_f,linewidth=2,text_tag=None):
		if text_tag is None:
			ax_f.plot(self.x,self.y,linewidth=2,label=self.text_tag)
		else:
			ax_f.plot(self.x,self.y,linewidth=2,label=text_tag)