#!/usr/bin/env python
# coding: utf-8
#

import numpy as np
from wopsego import Optimization, ValidOptimumNotFoundError

# Objective
def f_obj(x):
    """
    Function Six-Hump Camel Back
    2 global optimum y_opt =-1.0316 located at x_opt = (0.089842, -0.712656) or (-0.089842, 0.712656)
    https://www.sfu.ca/~ssurjano/camel6.html
    """
    x_ = np.atleast_2d(x)
    x1 = np.array(x_)[:, 0]
    x2 = np.array(x_)[:, 1]
    val = (
        4 * x1 ** 2
        - 2.1 * x1 ** 4
        + 1.0 / 3.0 * x1 ** 6
        + x1 * x2
        - 4 * x2 ** 2
        + 4 * x2 ** 4
    )
    return np.atleast_2d(val).T

xlimits = [[-3, 3], [-2, 2]]
optim = Optimization(xlimits)

xdoe = np.array(
    [
        [-0.91502224, 1.89017506],
        [2.57253436, 0.83786997],
        [-2.32304511, -1.12821447],
        [1.65152355, -1.63067708],
        [0.0057155, -0.31036381],
    ]
)
ydoe = f_obj(xdoe)
print("Initial DOE")
print("xdoe={}".format(xdoe))
print("ydoe={}".format(ydoe))

optim.tell_doe(xdoe, ydoe)

# We loop using the iteration budget
# Note: this loop is provided in as the run method of the optim object. See below.
n_iter = 15
for i in range(n_iter):
    x_suggested, status = optim.ask()
    print(
        "{} x suggested = {} with status: {}".format(
            i, x_suggested, Optimization.STATUSES[status]
        )
    )

    # compute objective function at the suggested point
    new_y = f_obj(np.atleast_2d(x_suggested))
    print("new y = {}".format(new_y))

    optim.tell(x_suggested, new_y)
    if optim.is_solution_reached():
        print("Solution is reached")
        break

    try:
        _, y = optim.get_result()
        print("y_opt_tmp = {}".format(y))
        print("")
    except ValidOptimumNotFoundError:  # in case no point in doe respect constraints yet
        pass

x_opt, y_opt = optim.get_result()
print("Found minimum y_opt = {} at x_opt = {}".format(y_opt, x_opt))
print(optim.get_result())
print(optim.get_history())

# For convenience, the previous optimization loop is available as the 'run' method of
# the optimization object.

# to reset the initial DOE, otherwise optimization will go on from previous state
# optim.tell_doe(xdoe, ydoe)

# run the optimization loop again
# optim.run(f_obj, 15)


# This code is referenced from
# https://github.com/probml/pmtk3/blob/master/demos/fisherDiscrimVowelDemo.m
# Author:Srikar-Reddy-Jilugu(@always-newbie161)

import numpy as np
import matplotlib.pyplot as plt
from scipy.io import loadmat
from sklearn.decomposition import PCA
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from fisher_lda_fit import fisher_lda_fit
import pyprobml_utils as pml
import requests
from io import BytesIO

url = 'https://github.com/probml/probml-data/blob/main/data/vowelTrain.mat?raw=true'
r = requests.get(url, allow_redirects=True)
rawdata = BytesIO(r.content)

def plot_projection_data(X, y, mu, nclasses, figure_num):
    """
    2d data is visualized with their respective symbol and color
    and the centroids of the data are plotted with black filled-in color.
    """

    # To match the Hastie color scheme
    lightblue = [55, 155, 255]
    orange = [255, 128, 0]
    magenta = [255, 0, 128]
    green2 = [132, 199, 71]
    cyan = [61, 220, 176]
    yellow = [255, 255, 0]
    brown = [128, 64, 0]
    blue = [0, 0, 255]
    red = [255, 0, 0]
    black = [0, 0, 0]
    gray = [128, 128, 128]

    colors = [lightblue, blue, brown, magenta, orange, cyan, gray, yellow, black, red, green2]

    plt.figure(figure_num)
    for c in range(0, nclasses):
        colors[c] = [col / 255 for col in colors[c]]
        ndx = np.where(y == (c + 1))
        plt.scatter(X[ndx, 0], X[ndx, 1], marker=symbols[c], s=30, facecolor="none", edgecolor=colors[c])
        plt.scatter(mu[c, 0], mu[c, 1], marker=symbols[c], s=40, facecolor="black")

data = loadmat(rawdata)
X = data['Xtrain']
y = data['ytrain']
nsamples, ndims = X.shape
nclasses = np.max(y)
K = 2

# ------------------------
# PCA projection

pca = PCA(K)
X_pca = pca.fit_transform(X)
X_pca = -X_pca  # make it look like the Hastie figure
muC = np.zeros((nclasses, ndims))
for c in range(0, nclasses):
    muC[c, :] = (np.mean((X[np.where(y == (c + 1))[0], :]), axis=0))

muC2d_pca = pca.fit_transform(muC)

symbols = '+ovd*.xs^d><ph'
plot_projection_data(X_pca, y, muC2d_pca, nclasses, figure_num=0)
plt.title('PCA projection of vowel data to 2d')
pml.savefig('fisherDiscrimVowelPCA.pdf')

# ------------------------
# FLDA projection

W = fisher_lda_fit(X, y, K)
W[:, 0] = -W[:, 0]  # make it look like the Hastie figure
X_lda = X @ W
muC2d_lda = muC @ W
plot_projection_data(X_lda, y, muC2d_lda, nclasses, figure_num=1)
plt.title('FLDA projection of vowel data to 2d')
pml.savefig('fisherDiscrimVowelLDA.pdf')

plt.show()


# %%
import numpy as np
import matplotlib.pyplot as plt

def fast_annealing_schedule(T, i):
    return T / i

def exponential_annealing_schedule(T, gamma):
    """
    Args:
        T: current temperature
        gamma: in (0, 1)
    """
    return T * gamma

def log_annealing_schedule(T, i):
    num = T * np.log(2)
    den = np.log(i+1)
    return num / den

def simulated_annealing(f, x0, T, tolerance, max_iterations):
    """
    Args:
        f: function to minimize
        x0: initial x value
        T: initial temperature
        tolerance: tolerance for stopping condition

    Returns:
        x_hist: history of x values as gradient descent updates x
        f_hist: history of f(x) values as gradient descent updates x
        iterations: number of iterations to reach tolerance
    """

    x_hist = []
    x_hist.append(x0)

    f_hist = []
    f_hist.append(f(x0))

    iterations = 0

    x = x0

    while True:
        iterations += 1
        T = log_annealing_schedule(T, iterations)

        # generate new sample
        x_new = np.random.multivariate_normal(x, np.identity(len(x)))

         # accept new sample if it is better
        if f(x_new) < f(x):
            x = x_new
        # otherwise, accept with some probability
        else:
            if np.random.rand() < np.exp((f(x) - f(x_new)) / T):
                x = x_new

        x_hist.append(x)
        f_hist.append(f(x))

        # if f_hist[-1] - f_hist[-2] < tolerance:
        #     break
        if iterations > max_iterations:
            break

    return x_hist, f_hist, iterations

if __name__ == '__main__':

    def f(x: np.ndarray) -> float:
        """
        f(x) = x_1**2 + x_2**2 + x_3**2 ... + x_n**2
        """
        Q = np.array([[2, 0, 0],
                      [0, 4, 0],
                      [0, 0, 6]])
        b = np.array([2, 2, 2])
        return 0.5 * (x.T @ Q @ x) - (b.T @ x)

    # random seed
    np.random.seed(8)

    x0 = x_init = np.full(3, 2.)
    tolerance = 1e-5
    T = 100
    iterations = 100

    x_hist, f_hist, iterations = simulated_annealing(f, x0, T, tolerance, iterations)
    print(f'final x value: {x_hist[-1]}')
    print(f'final f value: {f_hist[-1]}')
    print(f'iterations: {iterations-1}')

    # plot f_hist
    plt.plot(f_hist)
    plt.xlabel('iteration')
    plt.ylabel('$f(x)$')
    plt.title('Simulated annealing')
    plt.show()


#!/usr/bin/python3.7
# -*- coding: utf-8 -*-
# @Time  : 2019/11/7 16:01
# @Author: Jtyoui@qq.com
import numpy as np

def sigmoid(x):
    """Sigmoid函数"""
    return 1.0 / (1 + np.exp(-x))

def error_rate(h, label):
    """计算当前的错误率函数值

    :param h: 预测值
    :param label: 实际值
    :return: 错误率
    """
    m = np.shape(h)[0]
    sum_err = 0
    for i in range(m):
        if 0 < h[i, 0] < 1:
            sum_err -= label[i, 0] * np.log(h[i, 0]) + (1 - label[i, 0]) * np.log(1 - h[i, 0])
        else:
            sum_err -= 0
    return sum_err / m

def get_cost(predict: np.mat, label: np.mat) -> float:
    """计算损失函数的值

    :param predict: 预测值
    :param label: 标签
    :return: 损失函数的值
    """
    m = len(predict)
    error = 0.0
    for i in range(m):
        error -= np.log(sigmoid(predict[i, 0] * label[i, 0]))
    return error

def line_regression_a_b(x: np.array, y: np.array):
    """求解线性回归的a和β值。即y=b+a*x

    :param x: 数据特征值：应该是两维度。即：[[],[],[]]
    :param y: 数据预测值;一维度。即：[]
    :return: a值、和b值
    """
    var = np.var(x, ddof=1)  # 贝塞尔校正,方差
    cov = np.cov(x.transpose(), y)[0][1]  # 协方差
    x_ = np.mean(x)
    y_ = np.mean(y)
    a = cov / var
    b = y_ - a * x_
    return a, b

if __name__ == '__main__':
    a_, b_ = line_regression_a_b(np.array([[6], [8], [10], [14], [18]]), np.array([7, 9, 13, 17.5, 18]))
    print(np.array([[12]]) * a_ + b_)  # [[13.68103448]]


"""
Burak Himmetoglu, 2019

ElasticNet Implementation with coordinate descent optimization
"""
import random
import numpy as np
from mlbook.utils.losses import mse
from mlbook.linear_regression.common import predict

# -- Penalty term
def _penalty(beta, lam, al):
    p = 0.5 * (1-al) * np.sum(beta**2) + al * np.sum(np.abs(beta))
    return lam * p

# -- Loss function
def _loss(X, y, beta0, beta, lam, al):
    yHat = predict(X, beta0, beta)
    return 0.5 * mse(y, yHat) + _penalty(beta, lam, al)

# -- Update coefficients by coordinate descent
def _update_coef(c, X, y, beta0Hat, betaHat, s2, lam, al):
    _, p = X.shape
    yHat = predict(X, beta0Hat, betaHat)
    if c < p:
        yTilde = yHat - X[:,c] * betaHat[c]
        zc = np.mean((y - yTilde) * X[:,c])

        if np.abs(zc) > lam * al:
            if zc > 0:
                betaHat[c] = zc - lam * al
            else:
                betaHat[c] = zc + lam * al

            betaHat[c] /= (s2[c] + lam * (1 - al))
        else:
            betaHat[c] = 0.
    elif c == p:
        # Update bias term
        beta0Hat = np.mean(y - X @ betaHat)

    return beta0Hat, betaHat

# -- Fit by coordinate descent
def fit(X, y, lam, al, tol, maxIter, initBeta0 = None, initBeta = None):
    _, p = X.shape
    if initBeta is None:
        initBeta = np.random.randn(p)
    if initBeta0 is None:
        initBeta0 = 0.0

    beta0Hat, betaHat = initBeta0, initBeta
    curLoss = _loss(X, y, beta0Hat, betaHat, lam, al)
    if np.abs(curLoss) < tol:
        return beta0Hat, betaHat

    s2 = np.mean(X*X, axis=0)
    # Iterate over full coord. descent cycles
    for it in range(maxIter):
        # Loop over randomized coordinates
        randp = [x for x in range(p+1)]
        random.shuffle(randp)
        for c in randp:
            beta0Hat, betaHat = _update_coef(c, X, y, beta0Hat, betaHat, s2, lam, al)

            # New loss
            newLoss = _loss(X, y, beta0Hat, betaHat, lam, al)

            fit_summary = {'loss':curLoss,
                           'convIter':it,
                           'beta0Hat':beta0Hat,
                           'betaHat':betaHat}

        # Check convergence after one full cycle
        if np.abs(newLoss - curLoss) < tol:
            return fit_summary
        else:
            curLoss = newLoss

    print('No convergence in {:d} iterations'.format(it+1))
    return fit_summary


#!/usr/bin/env python
# coding: utf-8

#Plot the function

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

samples = 20
left_border = 0.01
right_border = 3
delta = (right_border - left_border) / samples
eps = 10 ** -8

def f(x):
    l = math.log(x)
    return 3 * l ** 2 + 6 * l - 5

def f_prime(x):
    l = math.log(x)
    return 6 * (l + 1) / x

def phi(x):
    return math.e ** ((-3 * math.log(x) ** 2 + 5) / 6)

def phi_prime(x):
    return -phi(x) * math.log(x) / x

def calc_f_values(x_values, f):
    f_values = np.zeros(np.shape(x_values))
    for i in range(samples):
        f_values[i] = f(x_values[i])
    return f_values

#Root separation

def separate_roots(interval, f, new_samples):
    global left_border
    left_border = interval[0]
    global right_border
    right_border = interval[1]
    global samples
    samples = new_samples
    x_values = np.linspace(left_border, right_border, samples)
    f_values = calc_f_values(x_values, f)
    intervals = np.empty((1, 2))
    init = False
    for i in range(samples - 1):
        if f_values[i + 1] * f_values[i] < 0:
            if not init:
                intervals[0] = [x_values[i], x_values[i + 1]]
                init = True
            else:
                intervals = np.vstack((intervals, [x_values[i], x_values[i + 1]]))
    return intervals

def dichotomy(f, init_intervals):
    def dichotomy_single_root(interval):
        if (interval[1] - interval[0] < delta):
            return interval
        print("[{}; {}]".format(interval[0], interval[1]))
        center = (interval[0] + interval[1]) / 2
        print(f(interval[0]) * f(center))
        if (f(interval[0]) * f(center) < 0):
            return dichotomy_single_root([interval[0], center])
        else:
            return dichotomy_single_root([center, interval[1]])

    for i in range(len(init_intervals)):
        init_intervals[i] = dichotomy_single_root(init_intervals[i])
    return init_intervals

def get_intervals_table(left, right, f, samples):
    intervals = separate_roots((left, right), f, samples)
    return intervals


import math
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.io import loadmat
import scipy.optimize as opt

data = loadmat('data/ex7data2.mat')
x = data['X']

def assignCentroids(x, μ):
	m = x.shape[0]
	c = np.zeros((m,))
	k = μ.shape[0]
	for i in range(m):
		min_dist = 1000000
		for j in range(k):
			dist = np.linalg.norm(x[i] - μ[j])
			if (dist < min_dist):
				min_dist = dist
				c[i] = j
	return c

def moveCentroids(x, c, k):
	m = x.shape[0]
	n = x.shape[1]
	μ = np.zeros((k, n))
	for i in range(k):
		tmp = np.array([x[ci] for ci in range(m) if c[ci] == i])
		if (tmp.shape[0] == 0):
			continue
		μ[i] = (tmp.sum(axis=0)) / np.float64(tmp.shape[0])
	return μ

def randomInit(x, k):
	#μ = np.array([x[int(np.random.rand() * k)] for i in range(k)])
	#the following is a better way of selecting random datasets from x
	#because using the above statement may select the same data point twice
	tmp = np.copy(x)
	np.random.shuffle(tmp)
	μ = tmp[:k,:]
	return μ

def formClusters(x, k, max_iters):
	#randomly initialze μ
	μ = randomInit(x, k)
	for i in range(max_iters):
		c = assignCentroids(x, μ)
		μ = moveCentroids(x, c, k)
	return μ, c

μ, c = formClusters(x, 3, 10)

print(μ)
print(c)
print(x.shape)

fig, ax = plt.subplots(figsize=(12,8))
ax.scatter(x[:,0], x[:,1], s=30, c=c, cmap='Blues')
plt.plot(μ[:,0], μ[:,1], 'rx')
plt.show()

'''
initial_centroids = np.array([[3, 3], [6, 2], [8, 5]], dtype=np.float64)
idx = assignCentroids(x, initial_centroids)
print(moveCentroids(x, idx, 3))
'''


try:
    import numpy as np
    import scipy.special as ss
    from discrete._base import Base
    from typing import Union, Optional, Tuple, Dict, List
    import math as m
except Exception as e:
    print(f'some modules are missin{e}')

class Infinite(Base):
    """
    Description:
        Base class for probability tags.
    """

    def __init__(self):
        if type(self) is Infinite:
            raise TypeError('base class cannot be instantiated.')

class Poisson(Infinite):
    """
    This class contains methods for evaluating some properties of the poisson distribution.
    As lambda increases to sufficiently large values, the normal distribution (λ, λ) may be used to
    approximate the Poisson distribution [#]_ [#]_ [#]_.

    Use the Poisson distribution to describe the number of times an event occurs in a finite observation space.

    .. math:: \\text{Poisson}(x;\\lambda) = \\frac{\\lambda ^{x} e^{- \\lambda}}{x!}

    Args:
        λ (float): expected rate if occurrences.
        x (int): number of occurrences.

    References:
        .. [#] Minitab (2019). Poisson Distribution. https://bityl.co/4uYc
        .. [#] Weisstein, Eric W. "Poisson Distribution." From MathWorld--A Wolfram Web Resource. https://mathworld.wolfram.com/PoissonDistribution.html.
        .. [#] Wikipedia contributors. (2020, December 16). Poisson distribution. https://en.wikipedia.org/w/index.php?title=Poisson_distribution&oldid=994605766
    """

    def __init__(self, λ: float):
        self.λ = λ

    def pmf(self, x: Union[List[int], int, np.ndarray]) -> Union[float, np.ndarray]:
        """
        Args:
            x (Union[List[int], int, np.ndarray]): random variable(s)

        Raises:
            TypeError: when types not of type integer
            ValueError: when x is less than 0

        Returns:
            Union[float, np.ndarray]: evaluation of pmf at x
        """

        if isinstance(x, (List, np.ndarray)):
            if not type(x) is np.ndarray:
                x = np.array(x)
            if not np.issubdtype(x[0], np.integer):
                raise TypeError('parameter x must be a positive integer')
            return (np.power(self.λ, x) * np.exp(-self.λ)) / np.vectorize(m.factorial, otypes=[object])(x)

        if x < 0:
            raise ValueError('parameter x must be a positive integer')
        return (pow(self.λ, x) * m.exp(-self.λ)) / m.factorial(x)

    def cdf(self, x: Union[List[int], int, np.ndarray]) -> Union[float, np.ndarray]:
        """
        Args:
            x (Union[List[int], int, np.ndarray]): data point(s) of interest

        Raises:
            TypeError: when types are not of type integer
            ValueError: when x is les than 0

        Returns:
            Union[float, np.ndarray]: evaluation of cdf at x
        """
        λ = self.λ

        if isinstance(x, (List, np.ndarray)):
            if not type(x) is np.ndarray:
                x = np.array(x)
            if not np.issubdtype(x[0], np.integer):
                raise TypeError('parameter x must be a positive integer')
            return ss.gammainc(m.floor(x + 1), λ) / np.vectorize(m.factorial, otypes=[object])(np.floor(x))

        if x < 0:
            raise ValueError('parameter x must be a positive integer')
        return ss.gammainc(m.floor(x + 1), λ) / m.factorial(m.floor(x))

    def mean(self) -> float:
        """
        Returns:
            the mean of Poisson Distribution.
        """
        return self.λ

    def median(self) -> float:
        """
        Returns:
            the median of Poisson Distribution.
        """
        λ = self.λ
        return λ + 1 / 3 - (0.02 / λ)

    def mode(self) -> Tuple[int, int]:
        """
        Returns:
            the mode of Poisson Distribution.
        """
        λ = self.λ
        return m.ceil(λ) - 1, m.floor(λ)

    def var(self) -> float:
        """
        Returns:
            the variance of Poisson Distribution.
        """
        return self.λ

    def skewness(self) -> float:
        """
        Returns:
            the skewness of Poisson Distribution.
        """
        return pow(self.λ, -0.5)

    def kurtosis(self) -> float:
        """
        Returns:
            the kurtosis of Poisson Distribution.
        """
        return 1/self.λ

    def summary(self) -> Dict[str, Union[float, Tuple[int, int]]]:
        """
        Returns:
            Dictionary of Poisson distirbution moments. This includes standard deviation.
        """
        return {
            'mean': self.mean(), 'median': self.median(), 'mode': self.mode(),
            'var': self.var(), 'std': self.std(), 'skewness': self.skewness(), 'kurtosis': self.kurtosis()
        }

class Zeta(Infinite):
    """
    This class contains methods concerning the Zeta Distribution [#]_ [#]_.

    .. math:: \\text{Zeta}(x;s) =\\frac{\\frac{1}{x^s}}{\\zeta(s)}

    Args:
        - s (float): main parameter
        - x (int): support parameter

    References:
        .. [#] Wikipedia contributors. (2020, November 6). Zeta distribution. In Wikipedia, The Free Encyclopedia. Retrieved 10:24, December 26, 2020, from https://en.wikipedia.org/w/index.php?title=Zeta_distribution&oldid=987351423
        .. [#] The Zeta Distribution. (2021, February 3). https://stats.libretexts.org/@go/page/10473
    """

    def __init__(self, s: float):
        self.s = s

    def pmf(self, x: Union[List[int], np.ndarray, int]) -> Union[float, np.ndarray]:
        """
        Args:
            x (Union[List[int], np.ndarray, int]): random variable(s)

        Raises:
            TypeError: when types are not of type integer

        Returns:
            Union[float, np.ndarray]: evaluation of pmf at x
        """
        s = self.s

        if isinstance(x, (List, np.ndarray)):
            if not type(x) is np.ndarray:
                x = np.array(x)
            if not np.issubdtype(x[0], np.integer):
                raise TypeError('random variables must be of type integer')

        return (1/x**s)/ss.zeta(s)

    def cdf(self, x: List[int]) -> Union[int, float, List[int]]:
        """
        Args:
            x (List[int]): random variables.

        Returns:
            Union[int, float, List[int]]: evaluation of cdf at x. Currently NotImplemented
        """
        return NotImplemented

    def mean(self) -> Union[str, float]:
        """
        Returns:
            mean of Zeta distribution
        """
        s = self.s
        if s > 2:
            return ss.zeta(s - 1) / ss.zeta(s)
        return "undefined"

    def median(self) -> str:
        """
        Returns:
            undefined.
        """
        return "undefined"

    def mode(self) -> int:
        """
        Returns:
            mode of Zeta distribution
        """
        return 1

    def var(self) -> Union[str, float]:
        """
        Returns:
            the variance of Zeta Distribution. Returns undefined if s <= 3.
        """
        s = self.s
        if s > 3:
            _x0 = ss.zeta(s)
            return (ss.zeta(s-2)/_x0) - (ss.zeta(s-1)/ss.zeta(s))**2
        return "undefined"

    def std(self) -> Union[str, float]:
        """
        Returns:
            the standard deviation of Zeta Distribution. Returns undefined if variance is undefined.
        """
        s = self.s
        if s > 3:
            _x0 = ss.zeta(s)
            return m.sqrt((ss.zeta(s-2)/_x0) - (ss.zeta(s-1)/ss.zeta(s))**2)
        return "undefined"

    def skewness(self) -> Union[str, float]:
        """
        Returns:
            the skewness of Zeta Distribution.
        """
        s = self.s
        if s <= 4:
            return "undefined"
        _x0 = ss.zeta(s-2)*ss.zeta(s)
        _x1 = ss.zeta(s-1)
        return (ss.zeta(s-3)*ss.zeta(s)**2 - 3*_x1*_x0 + 2*_x1**3) / pow(_x0-_x1**2, 3/2)

    def kurtosis(self) -> Union[str, float]:
        """
        Returns:
            the kurtosis of Zeta Distribution.
        """
        s = self.s
        if s <= 5:
            return "undefined"

        _x0 = ss.zeta(s-2)
        _x1 = ss.zeta(s)
        _x3 = ss.zeta(s-1)

        scale = 1/pow(_x0*_x1 - _x3**2, 2)
        numerator = (ss.zeta(s-4)*_x1**3) - (4*_x3*ss.zeta(s-3)
                                             * _x1**2) + (6*_x3**2*_x0*_x1-3*_x3**4)
        return scale*numerator

    def summary(self) -> Dict[str, Union[float, int, str]]:
        """
        Returns:
            Dictionary of Zeta distirbution moments. This includes standard deviation.
        """
        return {
            'mean': self.mean(), 'median': self.median(), 'mode': self.mode(),
            'var': self.var(), 'std': self.std(), 'skewness': self.skewness(), 'kurtosis': self.kurtosis()
        }

# class CMP(Infinite):
#     ...

# value checking on rv

class Borel(Infinite):
    """
    This class contains methods concerning the Borel Distribution [#]_.

    .. math::
        \\text{Borel}(x;\\mu) = \\frac{e^{-\\mu x}(\\mu x)^{x-1}}{x!}

    Args:
        mu (float): mu parameter :math:`\\mu \\in [0,1]`.
        x (int): random variables

    Reference:
        .. [#] Wikipedia Contributors (2021). Borel Distribution. https://en.wikipedia.org/wiki/Borel_distribution

    """

    def __init__(self, mu: float):
        if mu < 0 or mu > 1:
            raise ValueError('mu parameter must belong in the domain [0,1]')

        self.mu = mu

    def pmf(self, x: Union[List[int], int, np.ndarray]) -> Union[float, np.ndarray]:
        mu = self.mu
        if isinstance(x, (List, np.ndarray)):
            if not type(x) is np.ndarray:
                x = np.array(x)
            if not np.issubdtype(x[0], np.integer):
                raise TypeError(
                    'parameter x are expected to be of type integer.')
            return np.exp(-mu*x)*np.power(mu*x, x-1)/np.vectorize(m.factorial, otypes=[object])(x)

        return m.exp(-mu*x)*pow(x*mu, x-1)/m.factorial(x)

    def mean(self) -> float:
        return 1/(1-self.mu)

    def var(self) -> float:
        return self.mu/pow(1-self.mu, 3)

    def std(self) -> float:
        return m.sqrt(self.mu/pow(1-self.mu, 3))

    def summary(self) -> Dict[str, float]:
        """
        Returns:
            Dictionary of Borel distirbution moments. This includes standard deviation.
        """
        return {
            'mean': self.mean(), 'median': self.median(), 'mode': self.mode(),
            'var': self.var(), 'std': self.std(), 'skewness': self.skewness(), 'kurtosis': self.kurtosis()
        }

# class Benford(Infinite):
#     ...

# value checking on rv
class Logarithmic(Infinite):
    """This class contains methods concerning Logarithmic distirbution [#]_.

    .. math::
        \\text{Logarithmic}(x;p) = \\frac{-1}{\\ln(1-p)} \\ \\frac{p^k}{k}

    Args:
        p (float): p parameter
        x (int): random variable

    Reference:
        .. [#] Wikipedia Contributors (2020). Logarithmic distirbution. https://en.wikipedia.org/wiki/Logarithmic_distribution.
    """

    def __init__(self, p: float):
        if p <= 0 or p >= 1:
            raise ValueError(
                'parameter p is expected to be defined in the domain (0,1)')

        self.p = p

    def pmf(self, x: Union[List[int], int, np.ndarray]) -> Union[float, np.ndarray]:
        p = self.p
        x0 = -1/m.log(1-p)

        if isinstance(x, (List, np.ndarray)):
            if not type(x) is np.ndarray:
                x = np.array(x)
            if np.issubdtype(x[0], np.integer):
                raise TypeError(
                    'parameter x is expected to be of type integer')

            return x0*np.power(p, x)/x

        if not type(x) is int:
            raise TypeError('parameter x is expected to be of type integer')
        return x0*pow(p, x)/x

    def cdf(self, x: Union[List[int], int, np.ndarray]) -> Union[float, np.ndarray]:
        p = self.p

        if isinstance(x, (List, np.ndarray)):
            if not type(x) is np.ndarray:
                x = np.array(x)
            if np.issubdtype(x[0], np.integer):
                raise TypeError(
                    'parameter x is expected to be of type integer')
        else:
            if not type(x) is int:
                raise TypeError(
                    'parameter x is expected to be of type integer')

        return 1 + ss.betainc(p, x+1, 0)/m.log(1-p)

    def mean(self) -> float:
        p = self.p
        return (-1/m.log(1-p))*p/(1-p)

    def mode(self) -> float:
        return 1.0

    def var(self) -> float:
        p = self.p
        x0 = p**2 + p*m.log(1-p)
        x1 = pow(1-p, 2)*pow(m.log(1-p), 2)
        return - x0/x1

    def std(self) -> float:
        return m.sqrt(self.var())

    def summary(self) -> Dict[str, float]:
        """
        Returns:
            Dictionary of Logarithmic distirbution moments. This includes standard deviation.
        """
        return {
            'mean': self.mean(), 'median': self.median(), 'mode': self.mode(),
            'var': self.var(), 'std': self.std(), 'skewness': self.skewness(), 'kurtosis': self.kurtosis()
        }

# class Skellam(Infinite):
#     ...

# value checking on rv

class YulleSimon(Infinite):
    """
    This class contains methods concerning the Yulle-Simon Distribution [#]_.

    .. math::
        \\text{YulleSimon}(x;\\rho) = \\rho\\text{B}(x,\\rho+1)

    Args:
        shape (float): shape parameter :math:`\\rho > 0`
        x (float): random variables

    Reference:
        .. [#] Wikipedia Contributors (2021). Yulle-Simon distribution. https://en.wikipedia.org/wiki/Yule%E2%80%93Simon_distribution.
    """

    def __init__(self, shape: float):
        if shape <= 0:
            raise ValueError('shape parameter must be a positive real number')

        self.shape = shape

    def pmf(self, x: Union[List[int], int, np.ndarray]) -> Union[float, np.ndarray]:

        shape = self.shape
        if isinstance(x, (List, np.ndarray)):
            if not type(x) is np.ndarray:
                x = np.array(x)
            if np.issubdtype(x[0], np.integer):
                raise TypeError(
                    'parameter x is expected to be of type integer')

        else:
            if not type(x) is int:
                raise TypeError(
                    'parameter x is expected to be of type integer')

        return shape*ss.beta(x, shape+1)

    def cdf(self, x: Union[List[int], int, np.ndarray]) -> Union[float, np.ndarray]:
        shape = self.shape
        if isinstance(x, (List, np.ndarray)):
            if not type(x) is np.ndarray:
                x = np.array(x)
            if np.issubdtype(x[0], np.integer):
                raise TypeError(
                    'parameter x is expected to be of type integer')

        else:
            if not type(x) is int:
                raise TypeError(
                    'parameter x is expected to be of type integer')

        return (1-x)*ss.beta(x, shape+1)

    def mean(self) -> Union[float, str]:
        shape = self.shape

        if shape > 1:
            return shape/(shape-1)

        return 'Undefined'

    def mode(self) -> float:
        return 1.0

    def var(self) -> Union[float, str]:
        shape = self.shape
        if shape > 2:
            return shape**2/(pow(shape-1, 2)*(shape-2))
        return 'Undefined'

    def std(self) -> Union[float, str]:
        shape = self.shape
        if shape > 2:
            return m.sqrt(shape**2/(pow(shape-1, 2)*(shape-2)))
        return 'Undefined'

    def skewness(self) -> Union[float, str]:
        shape = self.shape
        if shape > 3:
            return pow(shape+1, 2)*m.sqrt(shape-2)/((shape-3)*shape)
        return 'Undefined'

    def kurtosis(self) -> Union[float, str]:
        shape = self.shape
        if shape > 4:
            x0 = (11*pow(shape, 3) - 49*shape - 22)/((shape-4)*(shape-3)*shape)
            return shape + 3 + x0
        return 'Undefined'

    def summary(self) -> Dict[str, Union[float, str]]:
        """
        Returns:
            Dictionary of Borel distirbution moments. This includes standard deviation.
        """
        return {
            'mean': self.mean(), 'median': self.median(), 'mode': self.mode(),
            'var': self.var(), 'std': self.std(), 'skewness': self.skewness(), 'kurtosis': self.kurtosis()
        }

class GaussKuzmin(Infinite):
    """This class contains methods concerning the Gauss-Kuzmin distribution [#]_ .

    .. math::
        \\text{GaussKuzmin}(x) = -\\log_2 \\Big[ 1- \\frac{1}{(k+1)^2}\\Big]

    Args:
        x (int): random variables :math:`x \\in (0,\\inf]`

    Reference:
        .. [#] Wikipedia Contributors (2021). Gauss-Kuzmin distribution. https://en.wikipedia.org/wiki/Gauss%E2%80%93Kuzmin_distribution.

    """

    def pmf(self, x: Union[List[int], int, np.ndarray]) -> Union[float,
                                                                 np.ndarray]: ...

    def cdf(self, x: Union[List[int], int, np.ndarray]) -> Union[float,
                                                                 np.ndarray]: ...

    def mean(self) -> float:
        return float('inf')

    def median(self) -> float:
        return 2.0

    def mode(self) -> float:
        return 1.0

    def var(self) -> float:
        return float('inf')

    def std(self) -> float:
        return float('inf')

    def skewness(self) -> str:
        return'Undefined'

    def kurtosis(self) -> str:
        return 'Undefined'

    def entropy(self) -> float:
        """ Reference:
        N. Blachman (1984). The Continued fraction as an information source (Corresp.).
        IEEE Transactions on Information Theor (Volume: 30, Issue: 4). DOI:  10.1109/TIT.1984.1056924.
        """
        return 3.432527514776

    def summary(self) -> Dict[str, Union[float, str]]:
        """
        Returns:
            Dictionary of Poisson distirbution moments. This includes standard deviation.
        """
        return {
            'mean': self.mean(), 'median': self.median(), 'mode': self.mode(),
            'var': self.var(), 'std': self.std(), 'skewness': self.skewness(), 'kurtosis': self.kurtosis()
        }


from sympy import *
from tait_bryan_R_utils import *
from rodrigues_R_utils import *
from quaternion_R_utils import *

pose_from = symbols('pose_from')
pose_to = symbols('pose_to')
pose_m = symbols('pose_m')

position_symbols_1 = [pose_from]
position_symbols_2 = [pose_to]
all_symbols = position_symbols_1 + position_symbols_2

wc_1 = Matrix([[pose_from]])
wc_2 = Matrix([[pose_to]])

cw_1=wc_1.inv()
#T_wc_1=Matrix([px_1, py_1, pz_1]).vec()
#T_cw_1=-R_cw_1*T_wc_1
#RT_cw_1=Matrix.hstack(R_cw_1, T_cw_1)
#RT_cw_1=Matrix.vstack(RT_cw_1, Matrix([[0,0,0,1]]))

relative_pose = cw_1 * wc_2

#parametrization = taitBryanFromMatrix44Case1(relative_pose)
#parametrization = rodriguesFromMatrix44(relative_pose)
#parametrization = quaternionFromMatrix44(relative_pose)
#t = relative_pose[0 : 3, 3]

target_value=Matrix([pose_m])

#target_value=Matrix([px_m, py_m, pz_m, sx_m, sy_m, sz_m])
#target_value=Matrix([px_m, py_m, pz_m, q0_m, q1_m, q2_m, q3_m])
model_function=relative_pose
delta=target_value-model_function
delta_jacobian=delta.jacobian(all_symbols)

print(delta)
print(delta_jacobian)

with open("relative_pose_one_dimentional_example_jacobian.h",'w') as f_cpp:
    f_cpp.write("inline void relative_pose_obs_eq(Eigen::Matrix<double, 1, 1> &delta, double pose_from, double pose_to, double pose_m)\n")
    f_cpp.write("{")
    for i in range (1):
        f_cpp.write("delta.coeffRef(%d,%d) = %s;\n"%(i, 0, ccode(delta[i])))
    f_cpp.write("}")
    f_cpp.write("\n")
    f_cpp.write("inline void relative_pose_obs_eq_jacobian(Eigen::Matrix<double, 1, 2, Eigen::RowMajor> &j, double pose_from, double pose_to)\n")
    f_cpp.write("{")
    for i in range (1):
        for j in range (2):
            f_cpp.write("j.coeffRef(%d,%d) = %s;\n"%(i,j, ccode(delta_jacobian[i,j])))
    f_cpp.write("}")
    f_cpp.write("inline void relative_pose(Eigen::Matrix<double, 1, 1> &relative_pose, double pose_from, double pose_to)\n")
    f_cpp.write("{")
    for i in range (1):
        f_cpp.write("relative_pose.coeffRef(%d,%d) = %s;\n"%(i, 0, ccode(model_function[i])))
    f_cpp.write("}")
    f_cpp.write("\n")


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

import numpy as np

def linealSolverForward(A, b):
    """Solves a system of equations given a lower triangular matrix.

    Arguments:
        A: Lower triangular matrix. Shape: (n, n)
        b: System's solutions. Shape: (n, 1)

    Raises:
        RuntimeError if A is not lower triangular

    Returns:
        A numpy array with the system's X vector. Shape: (n, 1)
    """
    # First we check if the matrix is a lower triangle
    if np.allclose(A, np.tril(A)):
        n = len(b)
        x = np.zeros((n, 1))

        # we apply the forward formula for every element of x
        for k in range(0, n):
            tempSum = []
            for number in range(0, k):
                tempSum.append(-1 * A[k][number] * x[number])
            tempSum = sum(tempSum)
            x[k] = (b[k] + tempSum) / A[k][k]

        return x

    else:
        raise RuntimeError("Matrix A is not lower triangular.")

def linealSolverBackwards(A, b):
    """Solves a system of equations given a upper triangular matrix.

    Arguments:
        A: Upper triangular matrix. Shape: (n,n)
        b: System's solutions. Shape: (n, 1)

    Raises:
        RuntimeError if A is not upper triangular

    Returns:
        A numpy array with the system's X vector. Shape: (n,1)
    """
    if np.allclose(A, np.triu(A)):
        n = len(b)
        x = np.zeros((n, 1))

        for k in reversed(range(0, n)):

            tempSum = []
            for number in range(k + 1, n):
                tempSum.append(-1 * A[k][number] * x[number])

            tempSum = sum(tempSum)
            x[k] = (b[k] + tempSum) / A[k][k]

        return x

    else:
        raise RuntimeError("Matrix A is not upper triangular.")

def cholesky(matrix):
    """Performs the cholesky descomposition into two matrices.

    Arguments:
        matrix: Hermitian and definite symmetric matrix to perfom Cholesky's
        descomposition.
            Must have shape (n,n)

    Raises:
        RuntimeError when an invalid matrix is given (ie. non Hermitian or
        non definite symmetric).

    Returns:
        Two numpy arrays.
            Both with shape (n,n)
    """

    # check if matrix is Cholesky compatible
    if matrix.shape[0] != matrix.shape[1]:
        raise RuntimeError("Matrix is not square.")

    # Is it symmetric?
    if not np.allclose(matrix, np.transpose(matrix)):
        raise RuntimeError("Matrix is not symmetric.")
    else:
        size = matrix.shape[0]

    # Now the algorithm itself

    lower = np.zeros(matrix.shape)

    # We iterate over the triangle from left to right and top to bottom
    for i in range(size):
        for j in range(i + 1):

            # The element belongs to the diagonal:
            if i == j:
                tosqrt = matrix[i][i] - np.sum(lower[i][:i]**2)
                if tosqrt <= 0:
                    raise RuntimeError("Matrix is not definite symmetric.")
                else:
                    lower[i][j] = np.sqrt(tosqrt)

            # The element *does not* belong to the diagonal
            else:
                sumatoria = []
                for z in range(j):
                    sumatoria.append(lower[i][z] * lower[j][z])
                sumatoria = sum(sumatoria)
                lower[i][j] = (matrix[i][j] - sumatoria) / lower[j][j]

    upper = np.matrix.transpose(lower)

    return lower, upper

def test_cholesky():
    """Test cholesky.

    This function will stop the code execution when it finds an error.

    Returns:
        None
    """

    # ====== Cholesky ======
    # Definite positive matrices
    # This matrices eigenvalues are > 0
    #
    # Eigenvalues sign has been verified using numpy's linalg.eig
    positiveMatrices = (np.array([[2, 3], [3, 6]]), np.array([[1, 2], [2, 5]]),
                        np.array([[57, 40, 7], [40, 78, 6], [7, 6, 13]]),
                        np.array([[6, 3, 4, 8], [3, 6, 5, 1], [4, 5, 10, 7],
                                  [8, 1, 7, 25]]),
                        np.array([[34, 12, 0, 0], [12, 41, 0, 0], [0, 0, 1, 0],
                                  [0, 0, 0, 1]]))

    # Not definite positive matrices
    # This matrices eigenvalues are < 0
    #
    # Eigenvalues sign has been verified using numpy's linalg.eig
    notPositiveMatrices = (np.array([[4, 2],
                                     [2, -1]]), np.array([[-1, 1], [1, 1]]),
                           np.array([[3, 8, 9], [8, -5, 4], [9, 4, 0]]),
                           np.array([[57, 40, 77, 30], [40, 78, 61, 69],
                                     [77, 61, 13, 59], [30, 69, 59, 81]]))

    # Non Hermitian matrices.
    # As their values are reals, this is the same as 'non symmetric matrices'.
    notHermitian = (np.array([[1, 3], [9, 7]]),
                    np.array([[1, 5, 7], [2, 4, 9], [0, 3, 0]]),
                    np.array([[5, 7, 5, 2], [9, 2, 6, 2], [40, 54, 78, 84],
                              [10, 43, 21, 19]]))

    print("="*60, "\nTesting cholesky() function...")

    # Definite positive matrices
    for testMatrix in positiveMatrices:
        print('-'*50)
        print(f'Testing definite positive matrix: \n{testMatrix}')
        try:
            A, B = cholesky(testMatrix)
            comparison = np.allclose(np.matmul(A, B), testMatrix)
            assert comparison, \
                "The last tested matrix did not pass the test."
            print("-> Pass <-")
        except RuntimeError:
            assert False, "The last tested matrix did not pass the test."

    # Not definite positive matrices
    # This matrices should raise and exception (as these aren't valid)
    for testMatrix in notPositiveMatrices:
        print('-'*50)
        print(f'Testing not definite positive matrix: \n{testMatrix}')
        try:
            cholesky(testMatrix)
            assert False, "The last tested matrix did not pass the test."
        except RuntimeError:
            assert True
            print("-> Pass <-")

    # Not Hermitian matrices
    # This matrices should raise and exception (as these aren't valid)
    for testMatrix in notHermitian:
        print('-'*50)
        print(f'Testing not Hermitian matrix: \n{testMatrix}')
        try:
            cholesky(testMatrix)
            assert False, "The last tested matrix did not pass the test."
        except RuntimeError:
            assert True
            print("-> Pass <-")

def leastsq(A, b):
    """Solves a least squares problem.
    Arguments:
        A: Numpy Matrix
        b: Numpy array with the points to approximate.
    Raises:
        RuntimeError if b is not a nx1 vector or the size of A (which is
        square) is different than n, also if either A or b are not arrays.
    Returns:
        A numpy array with the system's approximation
    """

    if type(A) != np.ndarray or type(b) != np.ndarray:
        raise RuntimeError("Input error! One of the leastq arguments is not a "
                           + "numpy array")

    if b.shape[1] != 1 or A.shape[0] != b.shape[0]:
        print('b', A.shape[1], b.shape[0])
        raise RuntimeError("b is not a nx1 vector or the size of A is "
                           + "different than n.")

    # D is A^t*A and E is A^t*b
    # D x = E
    D = np.matmul(np.matrix.transpose(A), A)
    E = np.matmul(np.matrix.transpose(A), b)

    # Separates the lower and upper part of the cholesky decomposition of D
    # lowD uppD x = E
    lowD, uppD = cholesky(D)

    # W is equal to uppD x, and thus is the solution for LowD W = E
    W = linealSolverForward(lowD, E)
    x = linealSolverBackwards(uppD, W)
    return x

if __name__ == "__main__":
    #print("Executed as stand-alone script. Running test function.\n")
    #test_cholesky()
    print(leastsq(np.array([[1, 2], [3, 4], [5, 6]]), np.array([[5], [11], [17]])))


import numpy as np

drng = np.random.default_rng()

def rotate_to_mu(X,mu):

    # Rotate [1,0,...,0] to mu
    dim = mu.size
    M = np.zeros((dim,dim))
    M[:,0] = mu/np.linalg.norm(mu)
    Q,R = np.linalg.qr(M)
    if R[0,0] < 0:
        Q = -Q
    Q *= np.linalg.norm(mu)
    return X@Q.T

def sample_vmf_canonical_mu(dim, k, rng=drng):
    """
    Generate samples from the von Mises-Fisher distribution
    with canonical mean, mu = [1,0,...,0]

    Reference:
      Simulation of the von Mises-Fisher distribution - Wood, 1994

    Inputs:
      dim: dimensionality of containing Euclidean space

      k: concentration parameter

    returns: one sample (dim, )

    """

    # VM*, step 0:
    b = (-2*k + np.sqrt(4*k**2 + (dim-1)**2))/(dim-1)  # (eqn 4)
    x0 = (1 - b)/(1 + b)
    c = k*x0 + (dim - 1)*np.log(1 - x0**2)

    done = False
    while not done:
        # VM*, step 1:
        Z = rng.beta((dim-1)/2, (dim-1)/2)
        W = (1.0 - (1.0 + b)*Z)/(1.0 - (1.0 - b)*Z)

        # VM*, step 2:
        logU = np.log(rng.uniform())
        done = k*W + (dim-1)*np.log(1-x0*W) - c >= logU

    # VM*, step 3:
    V = rng.normal(size=dim-1)
    V /= np.linalg.norm(V)

    X = np.append(W, V*np.sqrt(1 - W**2))
    return X

def sample_uniform(dim, n=None, rng=drng):
    randn = lambda *args: rng.normal(size=args)
    if n is None:
        r = randn(dim)
        return r/np.linalg.norm(r)
    R = randn(n, dim)
    return R/np.linalg.norm(R,axis=-1,keepdims=True)


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Fri Jul  9 17:22:40 2021

@author: alessandro
"""
import math
import numpy as np
import matplotlib.pyplot as plt

def trapezio(f, a, b, n):
    h = (b - a) / n
    nodi = np.arange(a, b + h, h)
    fnodi = f(nodi)
    return (h / 2) * (fnodi[0] + 2 * np.sum(fnodi[1:n]) + fnodi[n])

def integrale(f, a, b, tol, nmax = 2048):
    err, n = 1, 1
    i1 = trapezio(f, a, b, n)
    while n < nmax and err > tol:
        n *= 2
        i2 = trapezio(f, a, b, n)
        err = abs(i2 - i1) / 3
        i1 = i2
    return i2, n

def f(n): return lambda x: (x ** n) / (x + 10)

y = [math.log(11) - math.log(10)]

for i in range(2, 31):
    y.append((1 / (i - 1)) - 10 * y[i - 2])

z = np.zeros((31,))
for i in range(30, 0, -1):
    z[i - 1] = ((1 / 10) * ((1 / (i)) - z[i]) )

xk = np.arange(1, 31)
yk = []
zk = []
for n in range(0, 30):
    i, it = integrale(f(n + 1), 0, 1, 1e-6)
    print(str(i) + " -- " + str(it))

    erry = np.abs(y[n] - i) / np.abs(i)
    yk.append(erry)

    errz = np.abs(z[n] - i) / np.abs(i)
    zk.append(errz)

plt.semilogy(xk, yk, label="Errore y")
plt.semilogy(xk, zk, label="Errore z")
plt.legend()


import numpy as np
from sympy import *
from math import *

def pivotacaoParcial(A,I):

    p = 0
    m = None

    for i in range(0,A.shape[0]):
        for j in range(i+1,A.shape[0]):
            if A[i,i] < A[j,i]:
                p += 1
                Temp = np.copy(A[i])
                A[i] = np.copy(A[j])
                A[j] = np.copy(Temp)
                Temp2 = np.copy(I[i])
                I[i] = np.copy(I[j])
                I[j] = np.copy(Temp2)

        for k in range(i+1,A.shape[0]):
            d = np.copy(A[k,i])
            d = d/np.copy(A[i,i])
            A[k,:] = np.copy(A[k,:]) - (np.copy(A[i,:])*d)

    return [A,p,I]

def triangularSuperiorGaussJordan(A,I):
        for i in range(A.shape[0]-1,0,-1):
            for j in range(i-1,-1,-1):
                d = np.copy(A[j,i])/np.copy(A[i,i])
                A[j] = np.copy(A[j]) - np.copy(A[i])*d
                I[j] = np.copy(I[j]) - np.copy(I[i])*d
        R = np.copy(A[:,A.shape[1]-1])
        for k in range(0,A.shape[0]):
            R[k] = np.copy(R[k])/np.copy(A[k,k])
            I[k,:] = np.copy(I[k,:])/np.copy(A[k,k])
        return [A,I,R]

A = np.matrix(eval(input("Digite uma matriz : ")))
A = A.astype(float)
print("Linhas: "+str(A.shape[0]))
I = np.matrix([(0,0),(0,0)]) # Matriz identidade ainda não criada devidamente
I = I.astype(float)
ERR = False

if(A.shape[0] != A.shape[1]-1): # checa se a matriz é quadrada

    ERR = True;

for i in range(0,A.shape[0]):

    # criando matriz identidade para obtenção da matriz inversa de A
    I = np.asmatrix(np.identity(3))

if(ERR):

    print("-> Matriz inválida.") # O programa encerra por conta de entrada inválida

else:

      Ts = pivotacaoParcial(np.copy(A),np.copy(I)) # transforma a matriz A em triangular superior com pivotação parcial
      p = Ts[1]
      I = Ts[2]
      Ts = Ts[0]

      gaussJordan = triangularSuperiorGaussJordan(np.copy(Ts),np.copy(I)) #transforma a matriz A em matriz diagonal

      print("Resultado por eliminação de Gauss-Jordan: \n\n")
      print(gaussJordan[2])
      print(gaussJordan[0])


import numpy as np
import math
import functools as fu
import cv2
import random as rand

def transform_points(m, points):
    """ It transforms the given point/points using the given transformation matrix.
    :param points: numpy array, list
            The point/points to be transformed given the transformation matrix.

    :param m: An 3x3 matrix
            The transformation matrix which will be used for the transformation.
    :return: The transformed point/points.
    """
    ph = make_homogeneous(points).T
    ph = m @ ph
    return make_euclidean(ph.T)

def transform_image(image, m):
    """ It transforms the given image using the given transformation matrix.
    :param img: An image
            The image to be transformed given the transformation matrix.
    :param m: An 3x3 matrix
            The transformation matrix which will be used for the transformation.
    :return: The transformed image.
    """
    row, col, _ = image.shape
    return cv2.warpPerspective(image, m, (col, row))

def make_homogeneous(points):
    """ It converts the given point/points in an euclidean coordinates into a homogeneous coordinate
        :param points: numpy array, list
                The point/points to be converted into a homogeneous coordinate.
        :return: The converted point/points in the homogeneous coordinates.
    """
    if isinstance(points, list):
        points = np.asarray([points], dtype=np.float64)
        return np.hstack((points, np.ones((points.shape[0], 1), dtype=points.dtype)))
    else:
        return np.hstack((points, np.ones((points.shape[0], 1), dtype=points.dtype)))

def make_euclidean(points):
    """It converts the given point/points in a homogeneous coordinate into an euclidean coordinates.
    :param points: numpy array, list
            The point/points to be converted into an euclidean coordinates.
    :return: The converted point/points in the euclidean coordinates.
    """
    return points[:, :-1]

def identity():
    """ It provides an identity transformation matrix.
    :return: An identity matrix (3 x 3) using homogeneous coordinates.
    """
    return np.array([[1, 0, 0],
                     [0, 1, 0],
                     [0, 0, 1]],
                    dtype=np.float64)

def rotating(θ=0):
    """ It provides a rotation matrix given θ degrees which can then be used to rotate 2D point/points or an image
    clockwise about the origin. If you want to rotate counterclockwise pass a negative degree.
    :param θ: int
        The amount of degree to be rotated. The default value is 0 which means when using it to rotate it won't rotate
        the point/points or the image at all.
    :returns: The rotation matrix (3 x 3) using homogeneous coordinates.
    """
    θ = np.radians(θ)
    cos = math.cos(θ)
    sin = math.sin(θ)
    return np.array([[cos, sin, 0],
                     [-sin, cos, 0],
                     [0, 0, 1]],
                    dtype=np.float64)

def translating(t_x=0, t_y=0):
    """ It provides a translate matrix given quantity t_x and t_y for shifting x and y axes respectively.It can then
    be used to translate or ”shift” a 2D point/points or an image.
    as well as the y-axis by t_y.
    :param t_x: int
        The amount of shifting in the direction of the x-axis
    :param t_y: int
        The amount of shifting in the direction of the y-axis
    The default values for both are 0. That is it does not translate the point/points or the image when applied.
    :returns: The translation matrix (3 x 3) in homogeneous coordinates.
    """
    return np.array([[1, 0, t_x],
                     [0, 1, t_y],
                     [0, 0, 1]],
                    dtype=np.float64)

def scaling(scale_x=1, scale_y=1):
    """ It provides a scale matrix given quantity scale_x and scale_y for scaling x and y axes respectively.It can then
    be used to scale a 2D point/points or an image.

    scales (enlarge or shrink) the given 2D point/points in the direction of the x-axis by scale_x
    as well as the y-axis by scale_x.
    :param scale_x: int
        The scale factor by which we wish to enlarge/shrink the point/points in the direction of the x-axis.
    :param scale_y: int
        The scale factor by which we wish to enlarge/shrink the point/points in the direction of the y-axis.
    The default values for both are 1. That is it does not scale the point/points or the image when applied.
    :return: The scaling matrix (3 x 3) in homogeneous coordinates.
    """
    return np.array([[scale_x, 0, 0],
                     [0, scale_y, 0],
                     [0, 0, 1]],
                    dtype=np.float64)

def arbitrary():
    """
    :return: An (3 x 3) arbitrary transformation matrix using translating, scaling and rotating function randomly.
    """
    θ = rand.randint(-360, 361)
    r = rotating(θ)
    sx, sy = rand.sample(range(-10, 11), 2)
    s = scaling(sx, sy)
    tx, ty = rand.sample(range(-400, 401), 2)
    t = translating(tx, ty)
    I = identity()
    if 0 <= tx <= 200:
        return s @ t @ r @ I
    else:
        return r @ s @ I @ t

def invert(m):
    """ It provides a matrix for performing the inversion.
    :param m: a (3 x 3) matrix.
    :return: The inverse of the given matrix.
    """
    d = np.linalg.det(m)
    if d != 0:
        return np.linalg.inv(m).astype(dtype=np.float64)
    else:
        raise Exception("It is a non-invertible matrix")

def combine(*transformations):
    """ It combines the given transformation matrices.
    Be aware of which order you are passing the transformation matrices since it will be used to transform in that order.
    :param transformations: (3 x 3) transformation matrices. As many as you want.
        The matrices to be combined.
    :return: The combined matrix (3 x 3).
    """
    transformations = reversed(transformations)
    return fu.reduce(lambda tr1, tr2: tr1 @ tr2, transformations)

def learn_affine(srs, tar):
    """ It finds the affine transformation matrix between the two given triangles (3 points).
    A x = b     =>   x = inv(A) b
    :param srs: three 2D points in homogeneous coordinates representing a triangle.
        The source points.
    :param tar: three 2D points in homogeneous coordinates representing a triangle.
        The target pints.
    :return: The affine transformation matrix.
    """
    x1, x2, x3 = srs[0, 0], srs[1, 0], srs[2, 0]
    y1, y2, y3 = srs[0, 1], srs[1, 1], srs[2, 1]
    b = tar.flatten()
    a = np.array([[x1, y1, 1, 0, 0, 0],
                  [0, 0, 0, x1, y1, 1],
                  [x2, y2, 1, 0, 0, 0],
                  [0, 0, 0, x2, y2, 1],
                  [x3, y3, 1, 0, 0, 0],
                  [0, 0, 0, x3, y3, 1]],
                 dtype=np.float64)

    d = np.linalg.det(a)
    if d != 0:
        ai = np.linalg.inv(a)
        x = ai @ b
        x = x.flatten()
        a1, a2, a3, a4 = x[0], x[1], x[3], x[4]
        tx, ty = x[2], x[5]
        aff_transformation = np.array([[a1, a2, tx],
                                       [a3, a4, ty],
                                       [0, 0, 1]],
                                      dtype=np.float64)
        return aff_transformation
    else:
        raise Exception("It is a non-invertible matrix")


# Standard library imports
# /

# Third party imports
import itertools
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
from sklearn import cluster

# Local application imports
from scifin import timeseries as ts
from scifin import montecarlo as mc
from scifin import classifier as cl

# Generate two kinds of processes
N = 50
mc_MA = mc.generate_series(n=N, names_base="MA-", series_model=ts.moving_average,
                         start_date="2000-01-01", end_date="2020-01-01", frequency='M',
                         cst=1., order=2, coeffs=[0.5, 0.2], sigma=0.4)

mc_Garch = mc.generate_series(n=N, names_base="Garch-", series_model=ts.garch,
                         start_date="2000-01-01", end_date="2020-01-01", frequency='M',
                         cst=0.2, order_a=1, coeffs_a=[0.2], order_sig=1, coeffs_sig=[0.1])

# Combining them together
mc1 = [*mc_MA, *mc_Garch]

# Plot
ts.multi_plot(mc1)

# Shuffling elements
list_idx = [i for i in range(len(mc1))]
np.random.shuffle(list_idx)
mc1 = [mc1[i] for i in list_idx]

# Build Normalized DTW distance matrix based on 'abs'
obs1 = cl.dtw_distance_matrix_from_ts(mc1, window=10, mode='abs', normalize=True)

# Plot this DTW distance matrix
sns.heatmap(obs1, cmap='viridis')
plt.title("Initial DTW distance matrix")
plt.show()

# Fit the model
n_clust_range = range(2,4)
save_labels1, save_quality1 = cl.cluster_observation_matrix(X=obs1,
                                                            n_clust_range=n_clust_range,
                                                            model=cluster.KMeans,
                                                            verbose=False)

# Select the 2 clusters case
labels1 = save_labels1[2]
quality1 = save_quality1[2]

# Plot the clustered DTW distance matrix
clustered_obs1 = cl.reorganize_observation_matrix(X=obs1, labels=labels1)
sns.heatmap(clustered_obs1, cmap='viridis')
plt.title("Clustered DTW distance matrix")
plt.show()

# Find the most likely list of names ("expected truth")
name_perms = list(itertools.permutations(['MA', 'Ga']))
max_diag_sum = -1E10
for perm in name_perms:
    resu_matrix = cl.show_clustering_results(mc1, labels1, list(perm))
    diag_sum = np.trace(resu_matrix.values)
    if diag_sum > max_diag_sum:
        max_diag_sum = diag_sum
        expected_truth = list(perm)

# Show results
print()
clustering_results1 = cl.show_clustering_results(mc1, labels1, expected_truth)
print("Quality: ", quality1)
print("Trace: ", np.trace(clustering_results1.values))
print(clustering_results1)
print()

# Eventually plot the clusters content
cl.print_clusters_content(list_ts=mc1, labels=labels1)


"""
Derivation of the first MDE of the KdV equation with Zabusky and Kruska scheme.
"""
from sympy import *

# initialize sympy variables:
x, t, tau, h = symbols(['x', 't', 'tau', 'h'])
v = Function('v')
init_printing(use_unicode=True)

# Taylor expansions:
order = 10  # order of Taylor expansion
# Taylor Series around v(x,t) in x and t
v_t_plus_dt = sum(tau**i/factorial(i) * v(x, t).diff(t, i) for i in range(order))
v_t_minus_dt = sum((-tau)**i/factorial(i) * v(x, t).diff(t, i) for i in range(order))
v_x_minus_h = sum((-h)**i/factorial(i) * v(x, t).diff(x, i) for i in range(order))
v_x_plus_h = sum(h**i/factorial(i) * v(x, t).diff(x, i) for i in range(order))
v_x_minus_2h = sum((-2*h)**i/factorial(i) * v(x, t).diff(x, i) for i in range(order))
v_x_plus_2h = sum((2*h)**i/factorial(i) * v(x, t).diff(x, i) for i in range(order))

# build scheme from Taylor expanded terms and set it to 0; this yields the first MDE
scheme = (v_t_plus_dt - v_t_minus_dt) / (2 * tau) + (v_x_plus_h + v(x, t) + v_x_minus_h) * \
         (v_x_plus_h - v_x_minus_h) / h + (v_x_plus_2h - 2 * v_x_plus_h + 2 * v_x_minus_h - v_x_minus_2h) / (2 * h**3)
scheme_basis = simplify(scheme)

print('First MDE:\n')
pprint(expand(scheme))


#!/usr/bin/env python
# coding: utf-8

# In[27]:

import numpy as np
import matplotlib.pyplot as plt

from svg.path import parse_path
from svg.path.path import Line
from xml.dom import minidom

def line_splitter(start, end):
    return (lambda t: (1-t)*start+t*end)

def cubic_bezier_converter(start, control1, control2, end):
    original_data = np.array([start, control1, control2, end])
    cubic_bezier_matrix = np.array([
        [-1,  3, -3,  1],
        [ 3, -6,  3,  0],
        [-3,  3,  0,  0],
        [ 1,  0,  0,  0]
    ])
    return_data = cubic_bezier_matrix.dot(original_data)

    return (lambda t: np.array([t**3, t**2, t, 1]).dot(return_data))

# Learned from
# https://stackoverflow.com/questions/36971363/how-to-interpolate-svg-path-into-a-pixel-coordinates-not-simply-raster-in-pyth

# In[4]:

doc = minidom.parse('B_sample.svg')
path_strings = [path.getAttribute('d') for path
                in doc.getElementsByTagName('path')]
doc.unlink()

for path_string in path_strings:
    path = parse_path(path_string)
    for e in path:
        if type(e).__name__ == 'Line':
            x0 = e.start.real
            y0 = e.start.imag
            x1 = e.end.real
            y1 = e.end.imag
            print("(%.2f, %.2f) - (%.2f, %.2f)" % (x0, y0, x1, y1))

# In[59]:

block=0
n_dots=100
key=0
points_np=[]

path=parse_path(path_strings[block])

dat=path[key]
if type(path[key]).__name__=='CubicBezier':
    start_np = np.array([dat.start.real, dat.start.imag])
    control1_np = np.array([dat.control1.real, dat.control1.imag])
    control2_np = np.array([dat.control2.real, dat.control2.imag])
    end_np = np.array([dat.end.real, dat.end.imag])
    converted_curve = cubic_bezier_converter(start_np, control1_np, control2_np, end_np)
    #
    diff_np=start_np-end_np
    n_dots=np.round(np.linalg.norm(diff_np))
    #
    points_np = np.array([converted_curve(t) for t in np.linspace(0, 1, n_dots)])
elif type(path[key]).__name__=='Line':
    start_np = np.array([dat.start.real, dat.start.imag])
    end_np = np.array([dat.end.real, dat.end.imag])
    converted_line = line_splitter(start_np,end_np)
    #
    diff_np=start_np-end_np
    n_dots=np.round(np.linalg.norm(diff_np))
    #
    points_np=np.array([converted_line(t) for t in np.linspace(0, 1, n_dots)])
elif type(path[key]).__name__=='Move':
    #
    n_dots=1
    #
    start_np = np.array([dat.start.real, dat.start.imag])
    end_np = np.array([dat.end.real, dat.end.imag])
    points_np = np.array([start_np,end_np])
else:
    points_np=np.array([])

# == plot the line==
## controls_np = np.array([start_np, control1_np, control2_np, end_np])
#  curve segmentation

plt.plot(points_np[:, 0], points_np[:, 1], '.-')
# showing of control points
## plt.plot(controls_np[:,0], controls_np[:,1], 'o')
#  line drawing
## plt.plot([start_np[0], control1_np[0]], [start_np[1], control1_np[1]], '-', lw=1)
## plt.plot([control2_np[0], end_np[0]], [control2_np[1], end_np[1]], '-', lw=1)

plt.show()
print(points_np)

# In[231]:

block=0
n_dots=100
key=0

points_np_all=[]
points_np_all=np.empty((len(path_strings)),dtype=object)
print(len(points_np_all))
#points_np_all[k]=np.array([])

for k in range(len(path_strings)):
#for path_string in path_strings:
    path = parse_path(path_strings[k])
    points_np_merge=np.empty((0,2), float)
    #points_np_merge=np.empty(points_np_merge)
    for dat in path:

#path=parse_path(path_strings[block])

#dat=path[key]

        if type(dat).__name__=='CubicBezier':
            start_np = np.array([dat.start.real, dat.start.imag])
            control1_np = np.array([dat.control1.real, dat.control1.imag])
            control2_np = np.array([dat.control2.real, dat.control2.imag])
            end_np = np.array([dat.end.real, dat.end.imag])
            converted_curve = cubic_bezier_converter(start_np, control1_np, control2_np, end_np)
            #
            diff_np=start_np-end_np
            n_dots=np.round(np.linalg.norm(diff_np))
            #
            points_np = np.array([converted_curve(t) for t in np.linspace(0, 1, n_dots)])
        elif type(dat).__name__=='Line':
            start_np = np.array([dat.start.real, dat.start.imag])
            end_np = np.array([dat.end.real, dat.end.imag])
            converted_line = line_splitter(start_np,end_np)
            #
            diff_np=start_np-end_np
            n_dots=np.round(np.linalg.norm(diff_np))
            #
            points_np=np.array([converted_line(t) for t in np.linspace(0, 1, n_dots)])
        elif type(dat).__name__=='Move':
            #
            n_dots=1
            #
            start_np = np.array([dat.start.real, dat.start.imag])
            end_np = np.array([dat.end.real, dat.end.imag])
            points_np = np.array([start_np,end_np])
        else:
            points_np=np.array([])
        #points_np_merge=np.concatenate(points_np_merge,points_np)
        points_np_merge=np.append(points_np_merge, points_np, axis=0)
#         if k==0:
#             points_np_merge=points_np
#         else:
#             points_np_merge=np.append(points_np_merge,points_np,axis=0)
        plt.plot(points_np[:, 0], points_np[:, 1], '.-')
        plt.show()
        print(len(points_np))
        print(len(points_np_merge))
    #points_np_all1=points_np_all1.append(points_np_merge)
    #points_np_all=points_np_merge
    points_np_all[k]= points_np
#     points_np_all=points_np_all.append(points_np_merge)
    print(len(points_np_all))
    plt.plot(points_np_merge[:, 0], points_np_merge[:, 1], '.-')
    plt.show()

# == plot the line==
## controls_np = np.array([start_np, control1_np, control2_np, end_np])
#  curve segmentation

#for points_np in points_np_all:
## plt.plot(points_np[:, 0], points_np[:, 1], '.-')
# showing of control points
## plt.plot(controls_np[:,0], controls_np[:,1], 'o')
#  line drawing
## plt.plot([start_np[0], control1_np[0]], [start_np[1], control1_np[1]], '-', lw=1)
## plt.plot([control2_np[0], end_np[0]], [control2_np[1], end_np[1]], '-', lw=1)

##plt.show()
#print(points_np)
points_np_all

# In[233]:

len(points_np_all)
points_np_all[0]

# In[230]:

points_np_all=points_np_merge
print(len(points_np_all))
print(len(points_np_merge))
# points_np_merge=np.empty((1),dtype=object)
points_np_all=np.empty((len(path_strings)),dtype=object)

for k in range(len(path_strings)):
    points_np_all[k]= points_np
    print(len(points_np_all))

#     points_np_merge=points_np_merge.append(points_np)
# points_np_merge[1]= points_np
# print(len(points_np_all))

# In[226]:

len(path_strings)

# In[161]:

len(path_strings)
path_strings

# In[167]:

arr = np.empty((0,2), float)
arr = np.append(arr, points_np, axis=0)
arr

# In[170]:

arr = np.append(arr, points_np, axis=0)
arr
len(arr)

# In[109]:

len(points_np)
#points_np
points_np

# In[139]:

k
points_np_merge.shape
#np.vstack(points_np_merge,points_np)
points_np.shape

# In[147]:

#print(points_np_merge)
#print(points_np)
np.append(points_np_merge,points_np,axis=0)

# In[128]:

#points_np_merge=np.zeros((1, 2))
print(points_np_merge)
print(points_np)
points_np_merge=points_np_merge+points_np
#np.vstack((points_np_merge,points_np)

# In[103]:

np.zeros((0, 2))
#size(points_np_all)

# In[61]:

print(dat)
dir(dat.start)
# dat.start
# dat.end

# In[43]:

points_np

# In[31]:

dat=path[key]
dat

# In[41]:

key=0
dat=path[key]
dat

# In[9]:

block=0
n_dots=100
key=3

path=parse_path(path_strings[block])
dat=path[key]

start_np = np.array([dat.start.real, dat.start.imag])
end_np = np.array([dat.end.real, dat.end.imag])

print(start_np)
print(end_np)

diff_np=start_np-end_np
n_dots=np.round(np.linalg.norm(diff_np))

np.array([converted_curve(t) for t in np.linspace(0, 1, n_dots)])

# In[10]:

n_dots

# In[13]:

t=0.5
start_np=np.array([0,0])
end_np=np.array([100,100])
(1-t)*start_np+t*end_np

# In[16]:

def line_splitter(start, end):

    return (lambda t: (1-t)*start+t*end)

# In[34]:

diff_np=start_np-end_np
n_dots=np.round(np.linalg.norm(diff_np))

converted_line = line_splitter(start_np,end_np)
np.array([converted_line(t) for t in np.linspace(0, 1, n_dots)])

# In[22]:

n_dots

# In[26]:

diff_np=start_np-end_np
n_dots=np.round(np.linalg.norm(diff_np))
n_dots

# In[ ]:


import numpy as np

def turn(n):
    """Formula from WIkipedia.
    n could be numpy array of integers
    """
    return (((n & -n) << 1) & n) != 0

def dragon(N):
    """Generate dragon curve
    Returns a pair of integer arrays, (x,y), each 2^N elements long
    """
    t = turn(np.linspace(0, 2**N-1, 2**N, dtype=np.int32))

    a = np.remainder(np.cumsum(t*2-1), 4)

    #   1 | 0
    #   --+--
    #   2 | 3
    dx = np.array([1, -1, -1, 1], dtype=np.int32)
    dy = np.array([1, 1, -1, -1], dtype=np.int32)

    x = np.cumsum(dx[a])
    y = np.cumsum(dy[a])

    return x-((dx-1)//2)[a],y-((dy-1)//2)[a]

def dragon_binary_diagram(N):
    """Draw dragon curve on a bitmap
    Returned bitmap size is 2^N x 2^N
    """
    #Prepare canvas to draw curve
    D = np.zeros((2**N,2**N), dtype=np.float32)

    #Get curve. Scale is 2x.
    dx, dy = dragon(2*N-1)

    dx *= 2
    dy *= 2

    #Center the curve.
    cx, cy = (int(dx.mean()), int(dy.mean()))
    x0 = cx - D.shape[0]//2
    y0 = cy - D.shape[1]//2
    dx -= x0
    dy -= y0

    #Given array of coordinates, writes 1 at theese coordinates, when they are inside canvas.
    def putOnesAt(dx,dy):
        inside = (dx >= 0) & (dx < D.shape[0]) & (dy>=0) & (dy<D.shape[0])
        #Take part of x,y coordinates that are inside the image, and write repeated pattern by them
        #
        D[dx[inside],dy[inside]] = 1

    #Draw corners
    putOnesAt(dx,dy)

    #Draw midpoints between corners
    dx1 = (dx[0:-1]+dx[1:])//2
    dy1 = (dy[0:-1]+dy[1:])//2
    putOnesAt(dx1,dy1)
    return D

def showdragon(N):
    pp.plot(*(dragon(N)+()))
    pp.show()

if __name__=="__main__":
    from matplotlib import pyplot as pp
    order = 16
    print("Showing dragon curve of order {}".format(order))
    showdragon(order)


import numpy as np

def complex_mat():
    x = 1 + 2 * 1j
    # C = np.zeros((2, 2), dtype=np.complex_)
    C = np.zeros((2, 2), dtype=complex)
    C[0, 0] = 1 + 1j + x
    D = np.dot(C, C)
    print(D)

def matrix():
    I = np.eye(3)
    I[1, 1] = 0
    print(np.linalg.matrix_rank(I))

def solve():
    A = np.array([[2, -1], [-1, 2]])
    b = np.array([[0], [3]])
    x = np.linalg.solve(A, b)
    # x = np.linalg.inv(A).dot(b)  # equal, but slow
    print(x)
    print(np.linalg.det(A))
    print(np.linalg.norm(A))
    print(np.linalg.eig(A))

def main():
    solve()

if __name__ == '__main__':
    main()


from functools import partial
import jax
import jax.numpy as jnp

# def _dimension_check(x, y):
#     if x.shape != y.shape:
#         raise ValueError("x and y shapes are not the same")

@jax.jit
def _linear(x, y):
    return jnp.einsum("ij,ik->jk", x, y)

@jax.jit
def _rbf(x, y, gamma = 1.):
    # if jnp.ndim(x) == 1:
    #     x = x.reshape(-1, 1)
    #     y = y.reshape(-1, 1)
    xx = jnp.einsum("ik,ik->k", x, x).reshape(-1, 1)
    yy = jnp.einsum("ik,ik->k", y, y).reshape(1, -1)
    xy = _linear(x, y)
    d2 = xx + yy - 2 * xy
    return jnp.exp(-gamma * d2)

@jax.jit
def _poly(x, y, gamma = 1., r = 1., d = 2.):
    return jnp.power(gamma * _linear(x, y) + r, d)

@jax.jit
def _tanh(x, y, gamma = 1., r = 1.):
    return jnp.tanh(gamma * _linear(x, y) + r) # often called `sigmoid`

@jax.jit
def _cosine(x, y):
    '''
    Computing cosine similarity between x & y.
    '''
    xx = jnp.einsum("ik,ik->k", x, x).reshape(-1, 1)
    yy = jnp.einsum("ik,ik->k", y, y).reshape(1, -1)
    xy = _linear(x, y)
    return xy / (xx @ yy)


from statistics import mean
import random
import numpy as np
import matplotlib.pyplot as plt
# remember the function is y = m*x + b for linear regression model.
# this is sample data used to create model.
# xs = np.array([1, 3, 5, 6, 9, 10], dtype=np.float)
# ys = np.array([5, 6, 9, 8, 7, 11], dtype=np.float)

def dataset_generation(hm, variance, step=2, correlation=False):
    val = 1
    ys = []
    for y in range(hm):
        y = val + random.randrange(-variance, variance)
        ys.append(y)
        if correlation and correlation == 'pos':
            val += step
        if correlation and correlation == 'neg':
            val -= step
    xs = [i for i in range(len(ys))]
    return np.array(xs, dtype=np.float), np.array(ys, dtype=np.float)

def slope_of_line_and_intercept(xs, ys):
    m = (((mean(xs) * mean(ys)) - mean(xs * ys)) /
         (mean(xs)**2 - mean(xs**2)))
    b = mean(ys) - (m * mean(xs))
    return m, b

def squared_error(ys_og, ys_line):
    return sum((ys_og-ys_line)**2)

def coefficient_of_determination(ys_og, ys_line):
    ys_line_mean = [mean(ys_og) for y in ys_og]
    squared_error_reg = squared_error(ys_og, ys_line)
    squared_error_line = squared_error(ys_og, ys_line_mean)
    return 1 - (squared_error_reg / squared_error_line)

# tweak the values inside to check and see how the model performes.
xs, ys = dataset_generation(1000, 50, 2, correlation='pos')

m, b = slope_of_line_and_intercept(xs, ys)
reg_line = [(m*x+b) for x in xs]
r_squared = coefficient_of_determination(ys, reg_line)
x_input = 12
y_predict = m * x_input + b
print(r_squared)

plt.scatter(x_input, y_predict, s=100, color='g')
plt.scatter(xs, ys, color='black')
plt.plot(xs, reg_line, color='r')
plt.show()


import numpy as np
import pandas as pd

class FiniteDifferenceMethod1D:
    def __init__(self, time, surface, zone_air):
        # Explicit solver

        # General properties
        self.time = time
        self.surface = surface
        self.zone_air = zone_air

        # Stored variables
        self.temperature_array = None
        self.time_array = None

        # Number of internal points
        self.Nx = len(self.surface.layers)

        # Calculate Spatial Step-Size
        self.thickness = self.surface.thickness
        self.dx = self.thickness/self.Nx
        kx = self.dx/2

        # Create grid-points on x axis
        self.x = np.linspace(0,1,self.Nx+2)
        self.x = self.x[1:-1]

        # FD matrix
        self.A = None
        self.b = None
        self.u = None

        # Initial methods
        self.update_calculated_values()

    def update_calculated_values(self):
        self.setup_finite_difference_matrix()
        self.initialize_arrays()

    def setup_finite_difference_matrix(self):
        R = np.array(self.surface.thermal_resistance_array)
        C = np.array(self.surface.thermal_capacitance_array)
        dt = self.time.time_step
        Nx = self.Nx

        A1 = dt/(R[:-1]*C)
        A2 = 1-(dt/C)*(1/R[1:]+1/R[:-1])
        A3 = dt/(R[1:]*C)

        A = np.zeros((Nx,Nx+2))
        A[:,:-2] += np.diag(A1)
        A[:,1:-1] += np.diag(A2)
        A[:,2:] += np.diag(A3)

        self.A = A

    def initialize_arrays(self):
        #self.temperature_array = np.zeros((len(self.time.time_range),len(self.x)))
        #self.time_array = np.zeros(len(self.time.time_range))

        df = pd.DataFrame()
        for x in self.x:
            df[str(x)] = np.ones(self.time.length)*self.zone_air.initial_zone_air_temperature
        #df.index = self.time.time_range
        self.temperature_array = df
        self.time_array = pd.Series(self.time.time_range)

    def run_solver(self, iteration, time_index):
        surface = self.surface
        #t = self.time.time_range[start_time_step:end_time_step]
        x = self.x

        #for sim_index, time_index in enumerate(self.time_array[start_time_step:end_time_step].index):
        #array_index = start_time_step + sim_time_step
        if time_index > 0 and iteration == 0:
            b = np.array(self.temperature_array.loc[time_index-1])
        else:
            b = np.array(self.temperature_array.loc[time_index])

        # Boundary conditions
        inside_temperature = self.zone_air.zone_air_temperature.iloc[time_index]
        outside_temperature = self.surface.weather.dry_bulb_temperature.iloc[time_index]

        # Solve timestep
        self.solve_timestep(time_index, b, outside_temperature, inside_temperature)

    def solve_timestep(self, time_index, temperature_array, outside_temperature, inside_temperature):
        # Boundary Conditions
        T = outside_temperature
        b = np.insert(temperature_array,0,T,axis=0)
        b = np.append(b, inside_temperature)

        # Solve
        u = np.dot(self.A,b)
        b = np.array(u)

        # Store values in object
        self.temperature_array.iloc[time_index] = u


# -*- coding: utf-8 -*-
"""
Module de modélisation de courbes pour les sciences physiques
@author: David Thérincourt
"""

import numpy as np
from scipy.stats import linregress
from scipy.optimize import curve_fit

#--------------------------
# Fonctions mathématiques
#--------------------------

def lineaire(x, a) :
    """
    Fonction lineaire du type y = a*x

    Paramètres :
    x (liste ou tableau Numpy) : abscisses.
    a (float) :

    Retourne :
    Valeur de la fonction (float ou tableau Numpy)
    """
    return a*x

def parabole(x, a, b, c) :
    """
    Fonction parabolique du type y = a*x**2 + b*x + c

    Paramètres :
    x (liste ou tableau Numpy) : abscisses.
    a (float) :
    b (float) :
    c (float) :

    Retourne :
    Valeur de la fonction (float ou tableau Numpy)
    """
    return a*x**2+b*x+c

def exponentielle_croissante(x, A, tau, x0=0):
    """
    Fonction exponenetielle croissante du type y = A*(1-exp(-(x-x0)/tau))

    Paramètres :
    x (liste ou tableau Numpy) : abscisses.
    A (float)  : limite à l'infini.
    tau (float) : constante de temps.

    Paramètre optionnel :
    x0 (0 par défaut) : retard.

    Retourne :
    Valeur de la fonction (float ou tableau Numpy)
    """
    return A*(1-np.exp(-(x-x0)/tau))

def exponentielle_decroissante(x, A, tau, x0=0):
    """
    Fonction exponenetielle décroissante du type y = A*exp(-(x-x0)/tau)

    Paramètres :
    x (liste ou tableau Numpy) : abscisses.
    A (float)  : limite à l'infini.
    tau (float) : constante de temps.

    Paramètre optionnel :
    x0 (0 par défaut) : retard.

    Retourne :
    Valeur de la fonction (float ou tableau Numpy)
    """
    return A*np.exp(-(x-x0)/tau)

#---------------------------------------------
# Modélisations
#---------------------------------------------

def ajustement_affine(x, y):
    """
    Modélisation d'une fonction affine de la forme y = a*x + b

    Paramètres :
    x (liste ou tableau Numpy) : abscisses.
    y (liste ou tableau Numpy de même dimension que x) : ordonnées.

    Retourne un tuple (a, b) :
    a (float) : coefficient directeur.
    b (float) : ordonnée à l'origine.
    """
    a, b, _, _, _ = linregress(x,y)
    return a, b

def ajustement_lineaire(x, y, a_p0=1) :
    """
    Modélisation d'une fonction parabolique du type y = a*x

    Paramètres :
    x (liste ou tableau Numpy) : abscisses.
    y (liste ou tableau Numpy de même dimension que x) : ordonnées.

    Retourne :
    a (float)
    """
    (a), pcov = curve_fit(lineaire,x,y, p0=[a_p0])
    return a

def ajustement_parabolique(x, y) :
    """
    Modélisation d'une fonction parabolique du type y = a*x**2 + b*x + c

    Paramètres :
    x (liste ou tableau Numpy) : abscisses.
    y (liste ou tableau Numpy de même dimension que x) : ordonnées.

    Retourne :
    [a, b, c] (tableau) : coefficients
    """
    return np.polyfit(x, y, 2)

def ajustement_exponentielle_croissante(x, y, A_p0=1, tau_p0=1) :
    """
    Modélisation d'une série de points (x,y) par une fonction exponentielle croissante
    du type y = A*(1-exp(-x/tau))

    Paramètres :
    x (liste ou tableau Numpy) : abscisses.
    y (liste ou tableau Numpy de même dimension que x) : ordonnées.

    Paramètres optionnels :
    A_p0 (1 par défaut) : valeur de la limite à l'infini aidant à la convergence du modèle.
    tau_p0 (1 par défaut) : valeur de la constante de temps aidant à la convergence du modèle.

    Retourne un tuple (A, tau, x0) :
    A (float)  : limite à l'infini.
    tau (float) : constante de temps.
    """
    (A,tau), pcov = curve_fit(exponentielle_croissante,x,y, p0=[A_p0, tau_p0])
    return A, tau

def ajustement_exponentielle_croissante_x0(x, y, A_p0=1, tau_p0=1, x0_p0=0) :
    """
    Modélisation d'une série de points (x,y) par une fonction exponentielle croissante
    décalée suivant l'abscisse du type y = A*(1-exp(-(x-xo)/tau))

    Paramètres :
    x (liste ou tableau Numpy) : abscisses.
    y (liste ou tableau Numpy de même dimension que x) : ordonnées.

    Paramètres optionnels :
    A_p0 (1 par défaut) : valeur de la limite à l'infini aidant à la convergence du modèle.
    tau_p0 (1 par défaut) : valeur de la constante de temps aidant à la convergence du modèle.
    x0_p0 (0 par défaut) : valeur du retard aidant à la convergence du modèle.

    Retourne un tuple (A, tau, x0) :
    A (float)  : limite à l'infini.
    tau (float) : constante de temps.
    x0 (float) : retard.
    """
    (A,tau,x0), pcov = curve_fit(exponentielle_croissante,x,y, p0=[A_p0, tau_p0, x0_p0])
    return A, tau, x0

def ajustement_exponentielle_decroissante(x, y, A_p0=1, tau_p0=1) :
    """
    Modélisation d'une série de points (x,y) par une fonction exponentielle croissante
    du type y = A*exp(-x/tau)

    Paramètres :
    x (liste ou tableau Numpy) : abscisses.
    y (liste ou tableau Numpy de même dimension que x) : ordonnées.

    Paramètres optionnels :
    A_p0 (1 par défaut) : valeur de la limite à l'infini aidant à la convergence du modèle.
    tau_p0 (1 par défaut) : valeur de la constante de temps aidant à la convergence du modèle.

    Retourne un tuple (A, tau, x0) :
    A (float)  : limite à l'infini.
    tau (float) : constante de temps.
    """
    (A,tau), pcov = curve_fit(exponentielle_decroissante, x, y, p0=[A_p0, tau_p0])
    return A, tau

def ajustement_exponentielle_decroissante_x0(x, y, A_p0=1, tau_p0=1, x0_p0=1) :
    """
    Modélisation d'une série de points (x,y) par une fonction exponentielle croissante
    du type y = A*exp(-(x-x0)/tau)

    Paramètres :
    x (liste ou tableau Numpy) : abscisses.
    y (liste ou tableau Numpy de même dimension que x) : ordonnées.

    Paramètres optionnels :
    A_p0 (1 par défaut) : valeur de la limite à l'infini aidant à la convergence du modèle.
    tau_p0 (1 par défaut) : valeur de la constante de temps aidant à la convergence du modèle.

    Retourne un tuple (A, tau, x0) :
    A (float)  : limite à l'infini.
    tau (float) : constante de temps.
    x0 (float) : retard.
    """
    (A,tau, x0), pcov = curve_fit(exponentielle_decroissante, x, y, p0=[A_p0, tau_p0, x0_p0])
    return A, tau, x0


import numpy as np
import pprint

def random_A_and_B_matrix() -> np.array:
    """Genereting two matrix

    Returns:
        two np.array
    """
    a = np.random.randint(0, 5, size=(3, 3))
    b = np.random.randint(0, 5, size=(3, 1))
    return a, b

def find_matrix_X(matrix_A_inv: np.array, matrix_B: np.array) -> np.array:
    """Function for finding X matrix

    Args:
        matrix_A (np.array): matrix with shape (3,3)
        matrix_B (np.array): matrix with shape (3,1)

    Returns:
        np.array: result of multiplying two matrix
    """
    matrix_result = np.matmul(matrix_A_inv, matrix_B)
    return matrix_result

def main():
    # first matrix, shape (3,3)
    matrix_A = np.array([[1, 2, 3], [0, 1, 2], [2, 0, 0]])
    # print(np.linalg.inv(matrix_A))

    # second matrix, shape (3,1)
    matrix_B = np.array([[1], [1], [0]])

    # find X matrix
    matrix_X = find_matrix_X(np.linalg.inv(matrix_A), matrix_B)
    print(f"Result X matrix - {matrix_X}")

    # random testing
    try:
        test_A_matrix, test_B_matrix = random_A_and_B_matrix()
        print(find_matrix_X(np.linalg.inv(test_A_matrix), test_B_matrix))
    except np.linalg.LinAlgError as e:
        print(
            f"Some errors occured.\nImpossible to find the inverse matrix.\nThe given matrix is - {e}"
        )

if __name__ == "__main__":
    main()


import numpy as np

n= int(input("Number of points(order) (Enter between 1 to 6): "))
xi= int(input("Initial value of integration: "))
xf= int(input("Upper limit of integration: " ))
def guass_Quadrature(xi,xf,n):

    def f1(z):
        return 5 * z * np.exp(-2 * z)

    # def f2(z):
    #    return z ** 6 - 7 * z ^ 3

    def f3(z):
        return (xf-xi)/2*(f1((xf+xi)/2+z*(xf-xi)/2))

    y=0
    if n==1:
        w=[2]
        x=[0]

    elif n==2:
        w=[1.0000000000000000,1.0000000000000000]
        x=[-0.5773502691896257,0.5773502691896257]
        # for i in range(0,2):
        #    y+=w[i]*f1(x[i])
        # print(y)
    elif n==3:
        w=[0.8888888888888888,0.5555555555555556,0.5555555555555556]
        x=[0.0000000000000000,-0.7745966692414834,0.7745966692414834]
        # for i in range(0,3):
        #    y+=w[i]*f1(x[i])
        # print(y)

    elif n==4:
        w=[0.6521451548625461,0.6521451548625461,0.3478548451374538,0.3478548451374538]
        x=[-0.3399810435848563,0.3399810435848563,-0.8611363115940526,0.8611363115940526]
        # for i in range(0,4):
        #    y+=w[i]*f1(x[i])
        # print(y)

    elif n==5:
        w=[0.5688888888888889,0.4786286704993665,0.4786286704993665,0.2369268850561891,0.2369268850561891]
        x=[0.0000000000000000,-0.5384693101056831,0.5384693101056831,-0.9061798459386640,0.9061798459386640]
        # for i in range(0,5):
        #    y+=w[i]*f1(x[i])
        # print(y)

    elif n==6:
        w=[0.3607615730481386,0.3607615730481386,0.4679139345726910,0.4679139345726910,0.1713244923791704,0.1713244923791704]
        x=[0.6612093864662645,0.6612093864662645,0.2386191860831969,-0.2386191860831969,0.9324695142031521,-0.9324695142031521]
        # for i in range(0,6):
        #    y+=w[i]*f1(x[i])
        # print(y)

    else:
        print("invalid number of input")

    y=0
    if xi==-1 and xf ==1:
        for i in range(0,n):
            y+=(w[i]*f1(x[i]))
        print("The value of integration is: ",y)
    else:
        for i in range(0,n):
            y+=w[i]*f3(x[i])
        print("The value of integration is: ",y)

print(guass_Quadrature(xi,xf,n))


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

T = [1960, 1961, 1962, 1963, 1964, 1965, 1966, 1967, 1968]
S = [29.72, 30.61, 31.51, 32.13, 32.34, 32.85, 33.56, 34.20, 34.83]

xdata = np.array(T)
ydata = np.log(np.array(S))

def func(x, a, b):
    return a + b * x

popt, pcov = curve_fit(func, xdata, ydata)
print(popt)
print(pcov)

plt.plot(xdata, ydata, 'ko', label="Original Noised Data")
plt.plot(xdata, func(xdata, *popt), 'r', label="Fitted Curve")
plt.show()


from __future__ import division
import math
import numpy as np

def cal_mse(x, y):
    return ((x - y)**2).mean()

def cal_cross_entropy(x, y):
    """ Computes cross entropy between two distributions.
    Input: x: iterabale of N non-negative values
           y: iterabale of N non-negative values
    Returns: scalar
    """

    if np.any(x < 0) or np.any(y < 0):
        raise ValueError('Negative values exist.')

    # Force to proper probability mass function.
    x = np.array(x, dtype=np.float)
    y = np.array(y, dtype=np.float)
    x /= np.sum(x)
    y /= np.sum(y)

    # Ignore zero 'y' elements.
    mask = y > 0
    x = x[mask]
    y = y[mask]
    ce = -np.sum(x * np.log(y))
    return ce

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

def cal_softmax(x, t=-100.):
    x = x - np.max(x)
    if np.min(x) < t:
        x = x / np.min(x) * t
    exp_x = np.exp(x)
    out = exp_x / np.sum(exp_x, axis=-1, keepdims=True)
    return out

def cal_sqnr(signal_raw, signal_dequant, remove_zero=True):
    # SQNR is non-commutative
    # Unlike other distance function
    # Cannot change the order of signal_raw and signal_dequant
    raw = signal_raw.flatten()
    dequant = signal_dequant.flatten()

    if remove_zero is True:
        idx = dequant != 0
        raw = raw[idx]
        dequant = dequant[idx]

    noise = raw - dequant

    avg_raw = np.sum(raw) / raw.size
    avg_noise = np.sum(noise) / noise.size

    raw_zero_mean = raw - avg_raw
    noise_zero_mean = noise - avg_noise

    var_raw_zero_mean = np.sum(np.square(raw_zero_mean))
    var_noise_zero_mean = np.sum(np.square(noise_zero_mean))

    if var_noise_zero_mean == 0.0:
        return math.inf

    sqnr = 10 * np.log10(var_raw_zero_mean / var_noise_zero_mean)

    return sqnr

if __name__ == '__main__':
    raw = np.array([5.2, -4.1, 3.14, -2.1, 3.8, -1.2])
    dequant = np.array([5, -4, 3, -2, 4, -1])
    print(cal_sqnr(raw, dequant))


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

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

def graham_scan(coords):
    """Sort list so that first point is the lowest point in the numpy array"""
    coords = coords[np.argsort(coords[:, -1])]
    if len(coords) <= 4:
        raise RuntimeError("Convex hull not possible with less than three points")
    try:
        if coords[0][1] == coords[1][1]:
            """Sort by the y value then the x value if two y values are the same to find leftmost point"""
            coords = coords[np.lexsort((coords[:, 0], coords[:, 1]))]
    except IndexError:
        raise RuntimeError("Convex Hull not possible with less than three points")
    """Get Lowest Point then remove from the numpy array"""
    lowest_point = coords[0]
    p0 = Point(lowest_point[0], lowest_point[1])
    coords = coords[1:]     # Remove first value which is lowest point
    coords = np.array([[x, y, polar_angle(p0, Point(x, y))] for (x, y) in zip(coords.flat[0::2], coords.flat[1::2])])
    """Sort By Polar Angle W.R.T lowest point p0"""
    coords = coords[np.argsort(coords[:, -1])]
    coords = coords[:, [0, 1]]  # Remove polar angle once sorted
    coords = [Point(x, y) for (x, y) in zip(coords.flat[0::2], coords.flat[1::2])]
    sorted_points = coords
    hull = [p0, sorted_points[0]]
    del sorted_points[0]
    for point in sorted_points:
        while orientation(point, hull[-1], hull[-2]) <= 0:
            hull.pop()
        hull.append(point)

    return hull

def orientation(a, b, c):
    return (b.y - a.y) * (c.x - b.x) - (b.x - a.x) * (c.y - b.y)

def polar_angle(p0, p1):
    return atan2(p1.y - p0.y, p1.x - p0.x)

def benchmark(test_sizes):
    for size in test_sizes:
        coordinates = np.random.rand(size, 2)
        coords = [Point(x, y) for (x, y) in zip(coordinates.flat[0::2], coordinates.flat[1::2])]
        x_vals = [i.x for i in coords]
        y_vals = [i.y for i in coords]
        hull = graham_scan(coordinates)
        hull_x_vals = [i.x for i in hull]
        hull_y_vals = [i.y for i in hull]
        plt.scatter(x_vals, y_vals, color='green')
        plt.scatter(hull_x_vals, hull_y_vals, color='red')
        plt.show()

if __name__ == "__main__":
    sizes = [10, 50, 75, 100, 1000]
    benchmark(sizes)


import numpy as np
import matplotlib.pyplot as plt
import numpy.linalg as la

datosFull = np.loadtxt('numeros_20.txt')
x = datosFull[:,0]
y = datosFull[:,1]

# Primera Parte ---------------------------------------------------------------------------------------------------------

def fitCoef(x,y,M):
    S = np.power(np.transpose(np.repeat(x[None],M+1,axis=0)),np.linspace(0,M,M+1))
    Sinv = la.pinv(S) #Si se puede, usar pseudoinversa implementada en linalg
    return np.dot(Sinv,y)
def polyGen(coef,x):
    M = len(coef)-1
    powers = np.power(np.transpose(np.repeat(x[None],M+1,axis=0)),np.linspace(0,M,M+1))
    return np.sum(np.multiply(powers,coef),axis=1)
def chiSquare(y,t):
    return np.sum(np.power(np.subtract(y,t),2))

fig,axii = plt.subplots(2,2)

axes = list(axii[0])+list(axii[1])
Ms = [0,1,3,9]
E_rms = [[],[]]
for i in range(0,10):

    x_test = np.linspace(0,1)
    coefs = fitCoef(x[:10],y[:10],i)
    y_fit = polyGen(coefs,x_test) #Si era el otro fit, cambiar esto.

    E_rms[0].append(np.sqrt(chiSquare(polyGen(coefs,x[:10]),y[:10]))/10)
    E_rms[1].append(np.sqrt(chiSquare(polyGen(coefs,x[10:]),y[10:]))/10)

    if i in Ms:
        a = axes[Ms.index(i)]
        a.scatter(x[10:],y[10:],facecolors='none',edgecolors='b')
        a.scatter(x[:10],y[:10],c='grey')
        a.plot(x_test,y_fit,c='r')
        a.set_title("M = "+str(i))
        a.set_ylim(0,2)
        if i == 9:
            a.set_ylim(-2000,2000)

fig.tight_layout()
fig.savefig('PrimeraParte_Figura1.png')

Ms = range(0,10)

fig = plt.figure()
plt.plot(Ms,E_rms[0],c='r',label='Datos entrenamiento')
plt.scatter(Ms,E_rms[0],c='r')
plt.plot(Ms,E_rms[1],c='b',label='Datos prueba')
plt.scatter(Ms,E_rms[1],c='b')
plt.yscale('log')
plt.legend()
plt.savefig('PrimeraParte_Figura2.png')

# Segunda Parte ---------------------------------------------------------------------------------------------------------------

class PolyFit():
    def __init__(self,degree=0):
        self.M = degree+1
        self.betas = np.array([])
    def fit(self,x,y):
        S = np.power(np.transpose(np.repeat(x[None],self.M,axis=0)),np.linspace(0,self.M-1,self.M))
        Sinv = la.pinv(S)
        self.betas = np.dot(Sinv,y)
    def predict(self,x):
        powers = np.power(np.transpose(np.repeat(x[None],self.M,axis=0)),np.linspace(0,self.M-1,self.M))
        return np.sum(np.multiply(powers,self.betas),axis=1)
    def score(self,x,y):
        chi = np.sum(np.power(np.subtract(self.predict(x),y),2))
        return np.sqrt(chi/len(y))

fig,axii = plt.subplots(2,2)

axes = list(axii[0])+list(axii[1])
Ms = [0,1,3,9]
E_rms = [[],[]]
for i in range(0,10):
    hola = PolyFit(i)
    x_test = np.linspace(0,1)
    coefs = hola.fit(x[:10],y[:10])
    y_fit = hola.predict(x_test)

    E_rms[0].append(hola.score(x[:10],y[:10]))
    E_rms[1].append(hola.score(x[10:],y[10:]))

    if i in Ms:
        a = axes[Ms.index(i)]
        a.scatter(x[10:],y[10:],facecolors='none',edgecolors='b')
        a.scatter(x[:10],y[:10],c='grey')
        a.plot(x_test,y_fit,c='r')
        a.set_title("M = "+str(i))
        a.set_ylim(0,2)
        if i == 9:
            a.set_ylim(-2000,2000)

fig.tight_layout()
fig.savefig('SegundaParte_Figura1.png')

Ms = range(0,10)

fig = plt.figure()
plt.plot(Ms,E_rms[0],c='r',label='Datos entrenamiento')
plt.scatter(Ms,E_rms[0],c='r')
plt.plot(Ms,E_rms[1],c='b',label='Datos prueba')
plt.scatter(Ms,E_rms[1],c='b')
plt.yscale('log')
plt.legend()
plt.savefig('SegundaParte_Figura2.png')


"""
  Name     : c15_08.py
  Book     : Python for Finance (2nd ed.)
  Publisher: Packt Publishing Ltd.
  Author   : Yuxing Yan
  Date     : 6/6/2017
  email    : yany@canisius.edu
             paulyxy@hotmail.com
"""
import numpy as np
import scipy as sp
import statsmodels.api as sm
#
def breusch_pagan_test(y,x):
    results=sm.OLS(y,x).fit()
    resid=results.resid
    n=len(resid)
    sigma2 = sum(resid**2)/n
    f = resid**2/sigma2 - 1
    results2=sm.OLS(f,x).fit()
    fv=results2.fittedvalues
    bp=0.5 * sum(fv**2)
    df=results2.df_model
    p_value=1-sp.stats.chi.cdf(bp,df)
    return round(bp,6), df, round(p_value,7)
#
sp.random.seed(12345)
n=100
x=[]
error1=sp.random.normal(0,1,n)
error2=sp.random.normal(0,2,n)
for i in range(n):
    if i%2==1:
        x.append(1)
    else:
        x.append(-1)
#
y1=x+np.array(x)+error1
y2=sp.zeros(n)
#
for i in range(n):
    if i%2==1:
        y2[i]=x[i]+error1[i]
    else:
        y2[i]=x[i]+error2[i]

print ('y1 vs. x (we expect to accept the null hypothesis)')
bp=breusch_pagan_test(y1,x)
#
print('BP value,	df,	p-value')
print 'bp =', bp
bp=breusch_pagan_test(y2,x)
print ('y2 vs. x	(we expect to rject the null hypothesis)')
print('BP value,	df,	p-value')
print('bp =', bp)

import numpy,import scipy,import statsmodels


#!/bin/python
# -*- UTF-8 -*-
# 1. import
import numpy as np
from matplotlib.pyplot import plot
from matplotlib.pyplot import show
# 2. Prepare data
bhp = np.loadtxt("BHP.csv", delimiter=',', usecols=(6, ), unpack=True)
vale = np.loadtxt("vale.csv", delimiter=',', usecols=(6, ), unpack=True)
# 2. Covariance & coefficient
bhp_returns = np.diff(bhp) / bhp[: -1] #(x1-x0) / x0.
vale_returns = np.diff(vale) / vale[: -1]
covariance = np.cov(bhp_returns, vale_returns)
print("cov matrix", covariance)
print("cov matrix diagonal: ", covariance.diagonal())
print("cov matrix trace: ", covariance.trace())
print("corr matrix", covariance / (bhp_returns.std(ddof=1) * vale_returns.std(ddof=1)))
print("corr matrix", np.corrcoef(bhp_returns, vale_returns))
# Sync
avg_diff = np.mean(bhp - vale)
dev = np.std(bhp - vale)
print("Sync: ", np.abs(bhp[-1] - vale[1] - avg_diff) > 2 * dev)
# plot
t = np.arange(len(bhp_returns))
# show
#plot(t, bhp_returns, lw=1)
#plot(t, vale_returns, lw=2)
#show()
# 4.3 4.4 Polyfit
t = np.arange(len(bhp))
poly_diff = np.polyfit(t, bhp - vale, 3)
print("Polynomial fit", poly_diff)
print("Next value", np.polyval(poly_diff, t[-1] + 1))
# roots
print("Roots", np.roots(poly_diff))
# der
der = np.polyder(poly_diff)
print("Derivative", der)
# der roots
print("Extremas", np.roots(der))
# check
vals = np.polyval(poly_diff, t)
print("max point", np.argmax(vals))
print("min point", np.argmin(vals))

# show
#plot(t, bhp - vale)
#plot(t, vals)
#how()

#


import numpy as np
import matplotlib.pyplot as plt

#Llevando nuestro algoritmo a python

def estimate_b0_b1(x, y):
    n = np.size(x)
    #obtenemos los promedios de X y de Y
    m_x, m_y = np.mean(x), np.mean(y)

    #Calcular sumatoria de XY y mi sumatoria de XX
    Sumatoria_xy = np.sum((x-m_x)*(y-m_y))
    Sumatoria_xx = np.sum(x*(x-m_x))

    #coeficientes de regresion
    b_1 = Sumatoria_xy / Sumatoria_xx
    b_0 = m_y - b_1*m_x

    return(b_0, b_1)

#Funcion de graficado
def plot_regression(x, y, b):
    plt.scatter(x, y, color = "g", marker = "o", s=30)

    y_pred = b[0] + b[1]*x
    plt.plot(x, y_pred, color = "b")

    #etiquetado
    plt.xlabel('x-Independiente')
    plt.ylabel('y-Dependiente')

    plt.show()

    # Codigo MAIN
def main():
        # DATASET
        x = np.array([1, 2, 3, 4, 5])
        y = np.array([2, 3, 5, 6, 5])

        # Obtenemos b1 y b2
        b = estimate_b0_b1(x, y)
        print("Los valores b0 = {}, b1 ={}".format(b[0], b[1]))

        # Graficamos nuestra linea de regresion
        plot_regression(x, y, b)

if __name__ == "__main__":
    main()


#
# Created by Homayoun Heidarzadeh
#
import numpy as np

# Efficient row-wise distances

class EuclideanRowWise:
    def __init__(self):
        pass

    def __call__(self, *args, **kwargs):
        x = args[0]
        matrix = args[1]
        return np.sum(np.abs(x - matrix) ** 2, axis=-1) ** (1. / 2)

    def __repr__(self):
        return "euclidean"

class ManhattanRowWise:
    def __init__(self):
        pass

    def __call__(self, *args, **kwargs):
        x = args[0]
        matrix = args[1]
        return np.sum(np.abs(x - matrix), axis=-1)

    def __repr__(self):
        return "manhattan"

class CosineRowWise:
    def __init__(self):
        pass

    def __call__(self, *args, **kwargs):
        x = args[0]
        matrix = args[1]
        return 1 - np.sum(matrix * x, -1) / ((np.sum(matrix ** 2, axis=-1) ** (1. / 2)) * np.linalg.norm(x))

    def __repr__(self):
        return "Cosine"

class MinkowskiRowWise:
    def __init__(self, p):
        self.p = p

    def __call__(self, *args, **kwargs):
        x = args[0]
        matrix = args[1]
        return np.sum(np.abs(x - matrix) ** self.p, axis=-1) ** (1. / self.p)

    def __repr__(self):
        return "Minkowski(p=%1.1f)" % self.p


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

# --- Rot Motion
freq1= 0.8
freq2= 0.4
tMax = 10
dt   = 0.1

omega1 = 2*np.pi*freq1
T1  = 1/freq1
omega2 = 2*np.pi*freq2
T2  = 1/freq2

time  = np.arange(0,tMax+dt/2,dt)

pos = np.zeros((len(time), 6)) # positions: x,y,z, theta_x, theta_y, theta_z
vel = np.zeros((len(time), 6)) # velocities: xdot, ydot, zdot, and omega
acc = np.zeros((len(time), 6)) # accelerations: xddot, omegadot

# -- First period we do a vertical motion
I1 = time <= T1
pos[I1,2] =           2*np.sin(omega1*time[I1])
vel[I1,2] = omega1   *2*np.cos(omega1*time[I1])
acc[I1,2] =-omega1**2*2*np.sin(omega1*time[I1])

# -- Second period we do nothing
I2 = time > T1

# -- Third period we do x rotations
I3 = time > 2*T1

pos[I3,3] =            0.10 *np.sin(omega2*time[I3])
vel[I3,3] = omega2   * 0.10 *np.cos(omega2*time[I3])
acc[I3,3] =-omega2**2* 0.10 *np.sin(omega2*time[I3])

cols = ['time_[s]', 'x_[m]', 'y_[m]', 'z_[m]' , 'theta_x_[rad]', 'theta_y_[rad]', 'theta_z_[rad]']
cols +=['xdot_[m/s]', 'ydot_[m/s]', 'zdot_[m/s]', 'omega_x_g_[rad/s]', 'omega_y_g_[rad/s]', 'omega_z_g_[rad/s]']
cols +=['xddot_[m^2/s]', 'yddot_[m^2/s]' , 'zddot_[m^2/s]',  'alpha_x_g_[rad/s]', 'alpha_y_g_[rad/s]', 'alpha_z_g_[rad/s]']

data=np.column_stack((time, pos, vel, acc))

df = pd.DataFrame( data=data, columns=cols)
df.to_csv('KiteMotionSimple.csv', index=False, sep=',', float_format='%10.6f')

print(df.shape)

# Time_[s] , x_[m], y_[m], z_[m] , theta_x_[rad], theta_y_[rad], theta_z_[rad-], xdot_[m/s], ydot_[m/s], zdot_[m/s], omega_x_g_[rad/s], omega_y_g_[rad/s], omega_z_g_[rad/s],  xddot_[m^2/s], yddot_[m^2/s] , zddot_[m^2/s],  alpha_x_g_[rad/s], alpha_y_g_[rad/s], alpha_z_g_[rad/s]

if __name__ == '__main__':
    pass