import math
import numpy as np
import scipy.io

# Import wordVecV.mat matrix
V = scipy.io.loadmat('wordVecV.mat')["V"]

# Get the “raw” term-by-document matrix
M = np.zeros((1651, 10))
for i in range(1651):
    for j in range(10):
        if V[i][j] > 0:
            M[i][j] = 1

# Get normalized M matrix
M_tilda = np.zeros((1651, 10))
norms_of_columns = np.zeros(10)

for j in range(10):
    squared_column_sum = 0
    for i in range(1651):
        squared_column_sum += pow(M[i][j], 2)
    norms_of_columns[j] = np.sqrt(squared_column_sum)

for i in range(1651):
    for j in range(10):
        M_tilda[i][j] = M[i][j]/norms_of_columns[j]

# Singular value decomposition of M_tilda
U, S, V_transpose = np.linalg.svd(M_tilda)

# Function that returns projection of vector onto subspace of u(k)
def projection_onto_u(vector, k):
    projection = np.zeros((1651, 1))
    for i in range(k):
        # Add projection of vector onto kth vector in subspace
        alpha = (np.inner(vector, U[:, i])/np.inner(U[:, i], U[:, i]))
        u_vector = U[:, i]
        # Add projection component
        for j in range(1651):
            projection[j] = projection[j] + (alpha * u_vector)[j]
    return projection

# Function that returns cosine similarity between two vectors
def cosine_similarity(d, q):
    # Term A is numerator, term B is denominator part, term C is other denominator part
    A = B = C = 0
    for i in range(1651):
        A += d[i] * q[i]
        B += d[i] * d[i]
        C += q[i] * q[i]
    similarity = A / (np.sqrt(B) * np.sqrt(C))
    return float(similarity)

# For every pair of d's(matrix columns of M_tilda) find the cosine similarity. Repeat for decreasing k
cosine_similarities = np.zeros((45, 9))

for k in range(9,0,-1):
    row = 0
    for i in range(10):
        for j in range(i + 1, 10):
            # Project document vectors onto subspace spanned by u(k)
            d_projection = projection_onto_u(M_tilda[:, i], k)
            q_projection = projection_onto_u(M_tilda[:, j], k)

            cosine_similarities[row][9 - k] = (cosine_similarity(d_projection, q_projection))
            row += 1

print("The most similar documents are the last two, Barack Obama and George W. Bush")
print("The lowest k can be without changing the answer is k = 3")


import sys

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

from scipy.misc import imread

def get_alignment(src_points, tgt_points):
    """Computes similarity matrix between src_points and tgt_points.

    Returns:
        a 2x3 numpy array, similarity matrix.
    """
    N = len(src_points)

    # We would like to solve: Ax=b
    ''' Build A and b '''
    A = np.empty((2*N, 4))
    b = np.empty((2*N, 1))
    i = 0
    for x, y in src_points:
        A[i,:]  = np.array([x, -y, 1, 0])
        A[i+1,:]= np.array([y, x, 0, 1])
        i += 2

    i = 0
    for x, y in tgt_points:
        b[i,:]  = np.array([x])
        b[i+1,:]  = np.array([y])
        i += 2

    ''' Inverse A and solve for x '''
    A_inv = np.linalg.pinv(A)
    x = np.matmul(A_inv, b)

    ''' Create Similarity Matrix from x '''
    '''         | a_1   -a_2   a_3 | '''
    ''' s_mat = | a_2    a_1   a_4 | '''
    '''         |  0      0     1  | '''
    #print('----------------')
    a_1 = x[0][0]
    a_2 = x[1][0]
    a_3 = x[2][0]
    a_4 = x[3][0]
    s_mat = np.array([[a_1, -a_2, a_3], [a_2, a_1, a_4], [0, 0, 1]])
    return s_mat

def test_alignment():
    """Tests our alignment matrix with 90 deg counter-clockwise rotation."""
    lena = imread('lena.png')

    #
    # Obtain mapping.
    #

    # Square
    src_points_x = [100, 100, 400, 400, 450]
    src_points_y = [100, 400, 100, 400, 450]
    tgt_points_x = [150, 150, 350, 350, 300]
    tgt_points_y = [150, 350, 150, 350, 300]

    src_points = zip(src_points_x, src_points_y)
    tgt_points = zip(tgt_points_x, tgt_points_y)
    s_mat = get_alignment(list(src_points), list(tgt_points))

    #
    # Apply on a test point
    #
    x, y = 400, 100
    src_point = np.array([x, y, 1])
    tgt_point = s_mat.dot(src_point)
    tgt_point_x = tgt_point[0]
    tgt_point_y = tgt_point[1]
    print('**** tgt_point ****')
    print(tgt_point)

    implot = plt.imshow(lena)
    plt.scatter(src_points_x, src_points_y, c='r', s=20)
    plt.scatter(tgt_points_x, tgt_points_y, c='b', s=20)
    plt.scatter(tgt_point_x, tgt_point_y, c='g', s=20)
    plt.show()

def test_rotate():
    # Obtain mapping.
    src_points = np.array([[100, 100], [400, 100], [400, 400], [100, 400]])
    dst_points = np.roll(src_points, 1, axis=0)
    s_mat = get_alignment(src_points, dst_points)
    M = s_mat[:-1]

    # Apply mapping.
    #lena = imread('lena.png')
    #implot = plt.imshow(lena)
    #plt.show()
    img = cv2.imread('lena.png')
    rows,cols,ch = img.shape
    #M = cv2.getAffineTransform(pts1,pts2)

    dst = cv2.warpAffine(img,M,(cols,rows))
    plt.subplot(121),plt.imshow(img),plt.title('Input')
    plt.subplot(122),plt.imshow(dst),plt.title('Output')
    plt.show()

def test_identity():
    # Obtain mapping.
    src_points = np.array([[100, 100], [400, 100], [400, 400], [100, 400]])
    dst_points = src_points
    s_mat = get_alignment(src_points, dst_points)
    M = s_mat[:-1]

    # Apply mapping.
    #lena = imread('lena.png')
    #implot = plt.imshow(lena)
    #plt.show()
    img = cv2.imread('lena.png')
    rows,cols,ch = img.shape
    #M = cv2.getAffineTransform(pts1,pts2)

    dst = cv2.warpAffine(img,M,(cols,rows))
    plt.subplot(121),plt.imshow(img),plt.title('Input')
    plt.subplot(122),plt.imshow(dst),plt.title('Output')
    plt.show()

def main():
    #test_alignment()
    #test_rotate()
    test_identity()

if __name__ == '__main__':
    sys.exit(main())


"""Softmax."""

import numpy as np

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

def softmax(x):
    """Compute softmax values for each sets of scores in x."""
    return np.exp(x)/np.sum(np.exp(x),axis=0)

print('Softmax matrix for scores: {}'.format(softmax(scores)))
print('Softmax matrix for scores*10: {}'.format(softmax(scores*10)))
print('Softmax matrix for scores/10: {}'.format(softmax(scores/10)))

# Plot softmax curves
import matplotlib.pyplot as plt
x = np.arange(-2.0, 6.0, 0.1)
scores = np.vstack([x, np.ones_like(x), 0.2 * np.ones_like(x)])

plt.plot(x, softmax(scores).T, linewidth=2)
plt.show()


# -- Imports --------------------------------------------------------------------------

from typing import (
    List
)
from sympy import simplify, symbols, sqrt

# -------------------------------------------------------------------------- Imports --

# -- Functions --------------------------------------------------------------------------

def fibonacci_loop(n: int) -> int:
    a, b = 0, 1
    if n == 1:
        return a
    elif n == 2:
        return b
    else:
        for _ in range(n - 2):
            a, b = b, a + b
        return b

def fibonacci_sym(n: int) -> int:
    x = symbols('x', nonnegative=True, integer=True)
    fib = 1 / sqrt(5) * (((1+sqrt(5))/2)**(n-1) - ((1-sqrt(5))/2)**(n-1))
    result = fib.subs(x, n)
    result = simplify(result)
    return result

def fibonacci_recursion(n: int) -> int:
    if n == 1:
        return 0
    elif n == 2:
        return 1
    else:
        return fibonacci_recursion(n-1) + fibonacci_recursion(n-2)

def fibonacci_list_loop(n: int) -> List[int]:
    return [fibonacci_loop(i) for i in range(1, n)]

def fibonacci_list_sym(n: int) -> List[int]:
    return [fibonacci_sym(i) for i in range(1, n)]

def fibonacci_list_recursion(n: int) -> List[int]:
    return [fibonacci_recursion(i) for i in range(1, n)]

# -------------------------------------------------------------------------- Functions --


import numpy as np
import pandas as pd
from scipy import stats
from scipy.fft import dct
import matplotlib.pyplot as plt
from sklearn.mixture import GaussianMixture

# Help taken from these websites below on how to apply the DCT
# https://docs.scipy.org/doc/scipy/reference/generated/scipy.fft.dct.html
# https://stackoverflow.com/questions/40104377/issiue-with-implementation-of-2d-discrete-cosine-transform-in-python
# including some parts of the algorithm from the matlab
# numericalFeatureGeneratorExample.m file provided in the course material

def featureGenerator(trainMatrix, n):
    features = np.zeros((n,13))

    i = 0
    while i < n:
        img = np.reshape(trainMatrix[i,1:len(trainMatrix[0])], (28,28))
        imgDCT = dct((dct(img, norm='ortho')).T, norm='ortho')
        diagDCT = np.diag(imgDCT) #extract diagonal
        rowDCT = imgDCT[0,:] # extract first row
        colDCT = imgDCT[:,0] #extract first column
        features[i,:]= [np.mean(diagDCT), np.std(diagDCT,ddof=1), stats.skew(diagDCT), stats.kurtosis(diagDCT,fisher=False),
            np.mean(rowDCT), np.std(rowDCT,ddof=1), stats.skew(rowDCT), stats.kurtosis(rowDCT,fisher=False),
            np.mean(colDCT), np.std(colDCT,ddof=1), stats.skew(colDCT), stats.kurtosis(colDCT,fisher=False),
            int(trainMatrix[i][0])]
        i+=1
    return features

def plot(trainMatrix, index):
    sub = 1
    i=0
    plt.figure()
    while sub <= len(index):
        plt.subplot(3,4,sub)
        img = np.reshape(trainMatrix[index[i],1:len(trainMatrix[0])], (28,28))
        plt.imshow(img, cmap='gray')
        sub+=1
        i+=1

    plt.show()

    return

if __name__ == '__main__':
    train = pd.read_csv("train.csv",header=0)
    trainMatrix = train.to_numpy()

    test = featureGenerator(trainMatrix,100)
    np.savetxt("test.csv", test, delimiter=",", fmt='%5.4f')

    x = [1, 2, 4, 7, 8, 9, 11, 12, 17, 22]
    plot(trainMatrix, x)

Algorithms for Data Science/Homework 2/Homework2_Q3_Q4.py


import numpy as np
from matplotlib import pyplot as plt
from sklearn.datasets import load_iris

def pca_use_org(data):
    cov_matrix = np.cov(data, rowvar=False)
    l, v = np.linalg.eig(cov_matrix)
    l_index = np.argsort(l)[::-1]
    l_ = l[l_index]
    v_ = v[:, l_index]
    data_trans = np.dot(data, v_)
    return data_trans, v_

if __name__ == "__main__":
    d_index = [0, 2]
    iris = load_iris()
    data = iris.data
    data = data[:, d_index]

    print('data=', data)
    data -= data.mean(axis=0)
    print('data=', data)

    data_trans, v = pca_use_org(data)

    vec_s = [0, 0]
    vec_1st_e = [2 * v[0, 0], 2 * v[0, 1]]
    vec_2nd_e = [2 * v[1, 0], 2 * v[1, 1]]

    plt.figure(figsize=[8, 8])
    plt.xlim(-4, 4)
    plt.ylim(-4, 4)
    plt.quiver(vec_s[0], vec_s[1], vec_1st_e[0], vec_1st_e[1],
               angles='xy', scale_units='xy', scale=1, color='r', label='1st')
    plt.quiver(vec_s[0], vec_s[1], vec_2nd_e[0], vec_2nd_e[1],
               angles='xy', scale_units='xy', scale=1, color='b', label='2nd')
    plt.grid()
    plt.legend()
    plt.scatter(data[:, 0], data[:, 1], c=iris.target)
    # plt.savefig('charts/fig-3.png')

    plt.figure(figsize=[8, 8])
    plt.subplot2grid((4, 1), (0, 0), rowspan=2)
    plt.title('1st principal - 2nd principal')
    plt.grid()
    plt.scatter(data_trans[:, 0], data_trans[:, 1], c=iris.target)
    plt.subplot2grid((4, 1), (2, 0))
    plt.tick_params(labelleft="off", left="off")
    plt.title('1st principal')
    plt.grid()
    plt.scatter(data_trans[:, 0], np.zeros(len(data_trans[:, 0])), c=iris.target)
    plt.subplot2grid((4, 1), (3, 0))
    plt.title('2nd principal')
    plt.grid()
    plt.tick_params(labelleft="off", left="off")
    plt.scatter(data_trans[:, 1], np.zeros(len(data_trans[:, 1])), c=iris.target)
    plt.tight_layout()
    plt.show()


"""
## Question 1: Create Datasets
"""

import numpy as np

n_dataset = 15
n_class = 10
n_class_size = 20

def checkSampleVariance():
  population = np.random.randint(1,100,200)
  for i in range(n_class):
    pop_class = population[n_class*i:n_class*(i + 1)]
    print(f'class {i}:')
    print(f'mean : {np.mean(pop_class)}')
    print(f'variance : {np.var(pop_class)}')
  print(f'Population mean : {np.mean(population)}')
  print(f'Population variance : {np.var(population)}')

for i in range(n_dataset):
  print(f"DATA SET {i + 1} : ")
  checkSampleVariance()


# Gaussian (a.k.a. normal) distribution
import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import norm

# Probability Density Function (PDF)
r = np.random.randn(1000)
p = norm.pdf(r)
plt.scatter(r,p)
plt.title("Probability Density Function (PDF)")
plt.xlabel("r")
plt.ylabel("p")
plt.show()

# Log Probability Density Function (PDF)
r = np.random.randn(1000)
p = norm.logpdf(r)
plt.scatter(r,p)
plt.title("Log Probability Density Function (PDF)")
plt.xlabel("r")
plt.ylabel("p")
plt.show()

# Cumulative Probability Density Function (PDF)
r = np.random.randn(1000)
p = norm.cdf(r)
plt.scatter(r,p)
plt.title("Cumulative Probability Density Function (PDF)")
plt.xlabel("r")
plt.ylabel("p")
plt.show()

# Log Cumulative Probability Density Function (PDF)
r = np.random.randn(1000)
p = norm.logcdf(r)
plt.scatter(r,p)
plt.title("Log Cumulative Probability Density Function (PDF)")
plt.xlabel("r")
plt.ylabel("p")
plt.show()

# Sampling from Gaussian Distribution (1D)
# Standard Deviation=1, Mean=0
r = np.random.randn(1000)
plt.hist(r, bins=100)
plt.title("Sampling from Gaussian Distribution (1D) - Standard Deviation=1, Mean=0")
plt.xlabel("r")
plt.ylabel("frequency")
plt.show()

# Sampling from Gaussian Distribution (1D)
# Standard Deviation=10, Mean=5
r= 10*np.random.randn(1000) + 5
plt.hist(r, bins=100)
plt.title("Sampling from Gaussian Distribution (1D) - Standard Deviation=10, Mean=5")
plt.xlabel("r")
plt.ylabel("frequency")
plt.show()

# Sample from Gaussian Distribution (2D)
# Standard Deviation=1, Mean=0
r = np.random.randn(1000, 2)
plt.scatter(r[:, 0], r[:, 1])
plt.title("Sampling from Gaussian Distribution (2D)")
plt.xlabel("r[:, 0]")
plt.ylabel("r[:. 1]")
plt.show()


import pandas as pd
import numpy as np
import scipy.stats as ss
from dython.nominal import theils_u, cramers_v
from sklearn.metrics import mean_squared_error

def mean_absolute_error(y_true: np.ndarray, y_pred: np.ndarray):
    """
    Returns the mean absolute error between y_true and y_pred.

    :param y_true: NumPy.ndarray with the ground truth values.
    :param y_pred: NumPy.ndarray with the ground predicted values.
    :return: Mean absolute error (float).
    """
    return np.mean(np.abs(np.subtract(y_true, y_pred)))

def euclidean_distance(y_true: np.ndarray, y_pred: np.ndarray):
    """
    Returns the euclidean distance between y_true and y_pred.

    :param y_true: NumPy.ndarray with the ground truth values.
    :param y_pred: NumPy.ndarray with the ground predicted values.
    :returns: Mean absolute error (float).
    """
    return np.sqrt(np.sum(np.power(np.subtract(y_true, y_pred), 2)))

def mean_absolute_percentage_error(y_true: np.ndarray, y_pred: np.ndarray):
    """
    Returns the mean absolute percentage error between y_true and y_pred. Throws ValueError if y_true contains zero values.

    :param y_true: NumPy.ndarray with the ground truth values.
    :param y_pred: NumPy.ndarray with the ground predicted values.
    :return: Mean absolute percentage error (float).
    """
    y_true, y_pred = np.array(y_true), np.array(y_pred)
    return np.mean(np.abs((y_true - y_pred) / y_true))

def rmse(y_true: np.ndarray, y_pred: np.ndarray):
    """
    Returns the root mean squared error between y_true and y_pred.

    :param y_true: NumPy.ndarray with the ground truth values.
    :param y_pred: NumPy.ndarray with the ground predicted values.
    :return: root mean squared error (float).
    """
    return np.sqrt(mean_squared_error(y_true, y_pred))

def cosine_similarity(y_true: np.ndarray, y_pred: np.ndarray):
    y_true, y_pred = y_true.reshape(-1), y_pred.reshape(-1)
    return np.sum(y_true * y_pred) / (np.sqrt(np.sum(y_true ** 2)) * np.sqrt(np.sum(y_pred ** 2)))

def column_correlations(dataset_a, dataset_b, categorical_columns, theil_u=True):
    """
    Column-wise correlation calculation between ``dataset_a`` and ``dataset_b``.

    :param dataset_a: First DataFrame
    :param dataset_b: Second DataFrame
    :param categorical_columns: The columns containing categorical values
    :param theil_u: Whether to use Theil's U. If False, use Cramer's V.
    :return: Mean correlation between all columns.
    """
    if categorical_columns is None:
        categorical_columns = list()
    elif categorical_columns == 'all':
        categorical_columns = dataset_a.columns
    assert dataset_a.columns.tolist() == dataset_b.columns.tolist()
    corr = pd.DataFrame(columns=dataset_a.columns, index=['correlation'])

    for column in dataset_a.columns.tolist():
        if column in categorical_columns:
            if theil_u:
                corr[column] = theils_u(dataset_a[column].sort_values(), dataset_b[column].sort_values())
            else:
                corr[column] = cramers_v(dataset_a[column].sort_values(), dataset_b[column].sort_vaues())
        else:
            corr[column], _ = ss.pearsonr(dataset_a[column].sort_values(), dataset_b[column].sort_values())
    corr.fillna(value=np.nan, inplace=True)
    correlation = np.mean(corr.values.flatten())
    return correlation


import numpy as np

class RectifiedLinearUnit(object):
    def __init__(self):
        pass

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

    def derivative(self, x, partial_derivative_idx=None):
        dx = np.zeros_like(x)

        if partial_derivative_idx is None:
            dx[x > 0] = 1
            return dx
        else:
            dx[x[:, partial_derivative_idx] > 0, partial_derivative_idx] = 1
            return dx

class Softmax(object):
    def __init__(self):
        pass

    def compute(self, x):
        exps = np.exp(x)
        return exps / np.sum(exps, axis=1)[:, None]

    def derivative(self, x, partial_derivative_idx=None):
        """
        Computes the derivative w.r.t. softmax input z_i
        :param x:
        :param i: index
        :return:
        """
        ps = self.compute(x)
        if partial_derivative_idx is None:
            # Compute derivative
            return ps * (1.0 - ps)

        p_i = ps[:, partial_derivative_idx]
        res = -p_i[:, None] * ps
        res[:, partial_derivative_idx] = p_i * (1.0 - p_i)
        return res


from pandas import read_csv
import numpy as np
from matplotlib import pyplot
from scipy.optimize import curve_fit
url='https://raw.githubusercontent.com/jbrownlee/Datasets/master/longley.csv'
dataframe= read_csv(url,header=None)
data=dataframe.values
xdata,ydata=data[:,4],data[:,-1]

def objective(x, a, b, c, d, e, f, g, k):
	return (a * x) + (b * x**2) + (c * x**3) + (d * x**4) + (e * x**5) + (f * x**6) + (g * x**7) + k

def objective2(x, a, k):
	return (a * x) + k

def objective3(x, a,b,c,k):
	return (a * x) + (b * x**2) + (c * x**3) +  k

def objective4(x, a,b,c,d,e,k):
	return (a * x) + (b * x**2) + (c * x**3) + (d * x**4) + (e * x**5) + k

popt,_ =curve_fit(objective,xdata,ydata,method='dogbox')

popt2,_ =curve_fit(objective2,xdata,ydata,method='dogbox')

popt3,_ =curve_fit(objective3,xdata,ydata,method='dogbox')

popt4,_ =curve_fit(objective4,xdata,ydata,method='dogbox')

pyplot.subplot(2,2,1)
pyplot.scatter(xdata, ydata)
x_line = np.arange(min(xdata), max(xdata), 1)
y_line = objective(x_line, *popt)
pyplot.plot(x_line, y_line, '--', color='red')
pyplot.title('7th order polynomial linear regression')
pyplot.xlabel("Population size ")
pyplot.ylabel("Employed people ")

pyplot.subplot(2,2,2)
pyplot.scatter(xdata, ydata)
x_line3 = np.arange(min(xdata), max(xdata), 1)
y_line3 = objective4(x_line3, *popt4)
pyplot.plot(x_line3, y_line3, '--', color='red')
pyplot.title('5th order polynomial linear regression')
pyplot.xlabel("Population size ")
pyplot.ylabel("Employed people ")

pyplot.subplot(2,2,3)
pyplot.scatter(xdata, ydata)
x_line2 = np.arange(min(xdata), max(xdata), 1)
y_line2 = objective3(x_line2, *popt3)
pyplot.plot(x_line2, y_line2, '--', color='red')
pyplot.title('3rd order polynomial linear regression')
pyplot.xlabel("Population size ")
pyplot.ylabel("Employed people ")

pyplot.subplot(2,2,4)
pyplot.scatter(xdata, ydata)
x_line1 = np.arange(min(xdata), max(xdata), 1)
y_line1 = objective2(x_line1, *popt2)
pyplot.plot(x_line1, y_line1, '--', color='red')
pyplot.title('1st order polynomial linear regression')
pyplot.xlabel("Population size ")
pyplot.ylabel("Employed people ")
pyplot.show()


"""Capabilities for sampling of random input parameters.

This module contains functions to sample random input parameters.

"""
import numpy as np

def cond_mvn(
    mean,
    cov,
    dependent_ind,
    given_ind=None,
    given_value=None,
    check_cov=True,
):
    r"""Conditional mean and variance function.

    This function provides the conditional mean and variance-covariance matrix of
    [:math:`Y` given :math:`X`],
    where :math:`Z = (X,Y)` is the fully-joint multivariate normal distribution with
    mean equal to ``mean`` and covariance matrix ``cov``.

    This is a translation of the main function of R package condMVNorm_.

    .. _condMVNorm: https://cran.r-project.org/package=condMVNorm

    Parameters
    ----------
    mean : array_like
           The mean vector of the multivariate normal distribution.

    cov : array_like
            Symmetric and positive-definite covariance matrix of
            the multivariate normal distribution.

    dependent_ind : int or array_like
                    The indices of dependent variables.

    given_ind : array_like, optional
                The indices of independent variables (default value is `None`).
                If not specified return unconditional values.

    given_value : array_like, optional
              The conditioning values (default value is `None`). Should be the same length as
              ``given_ind``, otherwise throw an error.

    check_cov : bool, optional
                  Check that ``cov`` is symmetric, and all eigenvalue is positive
                  (default value is `True`).

    Returns
    -------
    cond_mean : numpy.ndarray
                The conditional mean of dependent variables.

    cond_cov : numpy.ndarray
               The conditional covariance matrix of dependent variables.

    Examples
    --------
    >>> mean = np.array([1, 1, 1])
    >>> cov = np.array([[4.0677098, -0.9620331, 0.9897267],
    ...                   [-0.9620331, 2.2775449, 0.7475968],
    ...                   [0.9897267, 0.7475968, 0.7336631]])
    >>> dependent_ind = [0, ]
    >>> given_ind = [1, 2]
    >>> given_value = [1, -1]
    >>> cond_mean, cond_cov = cond_mvn(mean, cov, dependent_ind, given_ind, given_value)
    >>> np.testing.assert_almost_equal(cond_mean, -4.347531, decimal=6)
    >>> np.testing.assert_almost_equal(cond_cov, 0.170718, decimal=6)
    """
    dependent_ind_np = np.array(dependent_ind)
    mean_np = np.array(mean)
    cov_np = np.array(cov)
    given_ind_np = np.array(given_ind, ndmin=1)
    given_value_np = np.array(given_value, ndmin=1)

    # Check `cov` is symmetric and positive-definite:
    if check_cov:
        if not np.allclose(cov_np, cov_np.T):
            raise ValueError("cov is not a symmetric matrix")
        elif np.all(np.linalg.eigvals(cov_np) > 0) == 0:
            raise ValueError("cov is not positive-definite")

    # When `given_ind` is None, return mean and variances of dependent values:
    if given_ind is None:
        cond_mean = np.array(mean_np[dependent_ind_np])
        cond_cov = np.array(cov_np[dependent_ind_np, :][:, dependent_ind_np])
        return cond_mean, cond_cov

    # Make sure that `given_value` aligns with `given_len`. This includes the case that
    # `given_value` is empty.
    if len(given_value_np) != len(given_ind_np):
        raise ValueError("lengths of given_value and given_ind must be the same")

    b = cov_np[dependent_ind_np, :][:, dependent_ind_np]
    c = cov_np[dependent_ind_np, :][:, given_ind]
    d = cov_np[given_ind, :][:, given_ind]
    c_dinv = c @ np.linalg.inv(d)

    cond_mean = mean_np[dependent_ind_np] + c_dinv @ (given_value - mean_np[given_ind])
    cond_cov = b - c_dinv @ c.T

    return cond_mean, cond_cov


from mandelbrotset.monte import *
import scipy.stats as st
import math

def conf_int(mean, var, n, p=0.95):
    pnew = (p+1)/2
    zval = st.norm.ppf(pnew)
    sigma = math.sqrt(var)
    alambda = (zval*sigma)/math.sqrt(n)
    min_lambda = mean - alambda
    plus_lambda = mean + alambda
    return f"Confidence interval: [{min_lambda:.4f} < X < {plus_lambda:.4f}] with p = {p}"

### Control Variets ###

## Simulations
z = 0.0j
step = 0.01
xmax= 0.5
xmin= -2.0
ymax= 1.1j
ymin= -1.1j

# amount of samples has to be a int if square root!
# in orther for orthogonal sampling to work
samples = 1024
simulations = 50
p_value = 0.95
maxiter = 200

EX = mandelbrot(xmax, xmin, ymax, ymin, maxiter) # gives 1.5139

# Simulations
rs_samples = []
lhs_samples = []
orth_samples = []
for n in range(1, simulations+1):
    r_sampling = random_sampling(xmax, xmin, ymax, ymin, maxiter, samples)
    lhs_sim = LHS(xmax, xmin, ymax, ymin, maxiter, samples, plot=False)
    orth_sim = orthogonal_sampling(xmax, xmin, ymax, ymin, maxiter, samples, plot=False)
    print(f"Simulation {n}, s={samples}, i={maxiter}, RS: {r_sampling}, LHS: {lhs_sim}, Orthogonal: {orth_sim}")
    rs_samples.append(r_sampling)
    lhs_samples.append(lhs_sim)
    orth_samples.append(orth_sim)

print()
print("NORMAL ESTIMATES: ")

print(f"\nEstimated Mandelbrot Area {EX}")
print(f"Simulations: {simulations}, Samples: {samples}\nVariance RS: {np.var(rs_samples)}\nVariance LHS: {np.var(lhs_samples)}\nVariance Orthogonal Sampling: {np.var(orth_samples)}\n ")
print(f"Estimated Mandelbrot Area E[X]: {EX:.4f}")
print(conf_int(np.mean(rs_samples), np.var(rs_samples), simulations, p=0.95))
print(conf_int(np.mean(lhs_samples), np.var(lhs_samples), simulations, p=0.95))
print(conf_int(np.mean(orth_samples), np.var(orth_samples), simulations, p=0.95))

print()
print("CONTROL VARIATES ESTIMATES: ")

mid = int(simulations/2)
cv_rs_x = rs_samples[:mid]
cv_rs_y = rs_samples[mid:]
cv_lhs_x = lhs_samples[:mid]
cv_lhs_y = lhs_samples[mid:]
cv_orth_x = orth_samples[:mid]
cv_orth_y = orth_samples[mid:]

cv_rs = [a_i - b_i + EX for a_i, b_i in zip(cv_rs_x, cv_rs_y)]
cv_lhs = [a_i - b_i + EX for a_i, b_i in zip(cv_lhs_x, cv_lhs_y)]
cv_orth = [a_i - b_i + EX for a_i, b_i in zip(cv_orth_x, cv_orth_y)]

print(f"\nEstimated Mandelbrot Area {EX}")
print(f"Simulations: {simulations}, Samples: {samples}\nVariance RS: {np.var(cv_rs)}\nVariance LHS: {np.var(cv_lhs)}\nVariance Orthogonal Sampling: {np.var(cv_orth)}\n ")
print(f"Estimated Mandelbrot Area E[X]: {EX:.4f}")
print(conf_int(np.mean(cv_rs), np.var(cv_rs), simulations, p=0.95))
print(conf_int(np.mean(cv_lhs), np.var(cv_lhs), simulations, p=0.95))
print(conf_int(np.mean(cv_orth), np.var(cv_orth), simulations, p=0.95))


import numpy as np
from pylab import scatter, show, title, xlabel, ylabel, plot, contour
import matplotlib.pyplot as plt

data = np.loadtxt("profits-population-data.txt", delimiter=",")
plt.scatter(data[:, 0], data[:, 1])
xlabel('Population of City in 10,000s')
ylabel('Profit in $10,000s')
#plt.show()

X = data[:, 0]
y = data[:, 1]
ones = np.ones(shape=(X.size))
X = np.c_[X,ones]
Y = np.ones(shape=(5, 2), dtype=np.int)
theta = np.zeros(shape=(2, 1)) # initialize fitting parameters
iterations = 1500;
alpha = 0.01;
#predictions = X.dot(theta)
#print(predictions)
#print(ones)

def computeCost(X, y, theta):

    # J = (1.0/(2*y.size))*(sum((X.dot(theta).flatten() - y)**2)) the entire formula

    m = y.size #number of training examples

    predictions = X.dot(theta).flatten() # multiply X matrix with theta and then flatten it to one dimension, this is the hypothesys h

    sqErrors = (predictions - y) ** 2 # give back the error squared

    J = (1.0 / (2 * m)) * sqErrors.sum() # the cost function

    return J

print(computeCost(X, y, theta))

def gradientDescent(X, y, theta, alpha, num_iters):

    m = y.size #number of training examples

    for i in range(num_iters):

        predictions = X.dot(theta).flatten()

def gradient_descent(X, y, theta, alpha, num_iters):
    '''
    Performs gradient descent to learn theta
    by taking num_items gradient steps with learning
    rate alpha
    '''
    m = y.size
    J_history = np.zeros(shape=(num_iters, 1))

    for i in range(num_iters):

        predictions = X.dot(theta).flatten()

        errors_x1 = (predictions - y) * X[:, 0]
        errors_x2 = (predictions - y) * X[:, 1]

        theta[0][0] = theta[0][0] - alpha * (1.0 / m) * errors_x1.sum()
        theta[1][0] = theta[1][0] - alpha * (1.0 / m) * errors_x2.sum()

        J_history[i, 0] = computeCost(X, y, theta)

    return theta, J_history

X = data[:, 0]
y = data[:, 1]

#number of training samples
m = y.size  # 97 in our dataset, the number of rows

# y intercept, the constant, the value at which the fitted line crosses the y axis.
#Add a column of ones to X (interception data)
it = np.ones(shape=(m, 2))
it[:, 1] = X

#Initialize theta parameters
theta = np.zeros(shape=(2, 1))

#Some gradient descent settings
iterations = 1500
alpha = 0.01

print(compute_cost(it, y, theta))

theta, J_history = gradient_descent(it, y, theta, alpha, iterations)

print(theta)
#Predict values for population sizes of 35,000 and 70,000
predict1 = np.array([1, 3.5]).dot(theta).flatten()
print('For population = 35,000, we predict a profit of %f' % (predict1 * 10000))
predict2 = np.array([1, 7.0]).dot(theta).flatten()
print('For population = 70,000, we predict a profit of %f' % (predict2 * 10000))

#Plot the results
result = it.dot(theta).flatten()
plt.plot(data[:, 0], result)
#plt.show()


import numpy as np
from scipy.stats import binom
from scipy.optimize import fmin

def compute_sigmoid(array):
    """
    """
    sigmoid = 1/(1 + np.exp(-array))
    return sigmoid

def compute_binom_neg_log_likelihood(p, n=16, k=9):
    """
    """
    negative_log_likelihood = - binom.logpmf(
        k=k,
        n=n,
        p=p
    )
    return negative_log_likelihood

def compute_binom_max_likelihood(start, n=16, k=9):
    """
    """
    solution, iterations = fmin(
        compute_binom_neg_log_likelihood,
        start,
        retall=True
    )
    solution = solution[0]
    iterations = [iter[0] for iter in iterations]
    return solution, iterations

def compute_MC_sampling(frozen_distro, max_sample=1000, iterations=100):
    """
    """
    sampled = {}
    samples = np.linspace(1, max_sample, iterations, dtype=int)
    for sample_size in samples:

        sampled[sample_size] = np.random.choice(frozen_distro, sample_size)

    return sampled

def compute_grid(para_1, para_2):
    """
    """
    grid = []
    for p_1 in para_1:

        for p_2 in para_2:

            grid.append([p_1, p_2])

    grid = np.array(grid)
    return grid

def compute_grid_growth(n_para, n_approx_points):
    """
    """
    grid_growth = [n_approx_points ** power for power in range(1, n_para)]
    return grid_growth

def compute_stats(array, ci=0.95, precis=2, sampling_prob=None):
    """
    """
    if sampling_prob is not None:
        sampled_array = np.random.choice(
            array,
            size=len(array),
            p=sampling_prob / sampling_prob.sum()
        )
    else:
        sampled_array = np.array(array)
    quantiles = np.quantile(sampled_array, [1.0 - ci, ci])
    stats = {
        'mean': sampled_array.mean(),
        'std': sampled_array.std(),
        'median': np.median(sampled_array),
        'lower': min(quantiles),
        'upper': max(quantiles)
    }
    for stat, value in stats.items():

        stats[stat] = np.round(value, precis)

    return stats

def compute_sp_posterior(prior, likelihood):
    """ Compute posterior probability

    Args:
        - prior:
        - likelihood:
    Returns:
        - posterior:
    """
    posterior = prior * likelihood
    posterior = posterior / np.sum(posterior)
    return posterior


from math import log10
import numpy as np

class EquationsSolver:

	def __init__(self, f, df = None):

		self.df = df

		if isinstance(f, (int, float)):

			self.f = lambda x: f

		elif callable(f):

			self.f = f

		else:

			raise Exception("The function is not defined")

	def __str__(self):

		try:

			return f"The interval or point: {self.x0}"

		except:

			raise Exception("Parametrs is not defined")

	def initial_conditions(self, x0, tol, maxiter = None):

		if tol <=0 or maxiter <=0:

			raise Exception("La toleracia o las iteraciones estan mal definidas")

		if isinstance(x0, (int, float)):

			self.point, self.interval = True, False
			x0 = float(x0)

		elif isinstance(x0, (list, tuple)):

			self.point, self.interval = False, True
			x0 = list(x0)

		else:

			raise Exception("The interval or point is not defined")

		self.x0, self.tol, self.maxiter = x0, tol, maxiter

class Bisection(EquationsSolver):

	def Solve(self):

		if isinstance(self.x0, (int, float)):

			raise ValueError("The interval is not defined")

		a, b  = self.x0
		f, tol = self.f, self.tol

		if a > b:

        		raise ValueError("Intervalo mal definido")

		if f(a) * f(b) >= 0.0:

			raise ValueError("La función debe cambiar de signo en el intervalo")

		if tol <= 0:

        		raise ValueError("La cota de error debe ser un número positivo")

		x = (a + b) / 2.0

		while True:

			if b - a < tol:

				return x

			elif np.sign(f(a)) * np.sign(f(x)) > 0:

            			a = x

			else:
				b = x

			x = (a + b) / 2.0

class Newton_Rhapson(EquationsSolver):

	def Solve(self):

		x, f, df, maxiter, tol = self.x0, self.f, self.df, self.maxiter, self.tol

		if df(x) == 0:

			raise ValueError("Division by zero. The method ended.")

		for i in range(maxiter):

		        dx = -f(x) / df(x)

		        x = x + dx

		        if abs(dx / x) < tol and abs(f(x)) < tol:

		            return x

		raise RuntimeError(f"There was no convergence after {maxiter} iterations")

class Secant(EquationsSolver):

	def Solve(self):

		f, maxiter, tol = self.f, self.maxiter, self.tol
		a, b = self.x0

		i = 0

		while i < maxiter:

			try:

				x = b - float(f(b))/(float(f(b) - f(a))/(b - a))

				er = abs(x-b)/abs(x)

			except ZeroDivisionError:

				print("Error en el denominador, para x = ", x)

				break

			if er < tol:

				return x

			a = b
			b = x
			i += 1

		return x


import numpy as np

def centroid(points):
    """
    Calculate the center of mass over a collection of points

    :param points: The points, expressed as numpy.array
    :type points: numpy.array

    :return: The center of mass for the given points
    :rtype: numpy.array
    """
    com = np.mean(points, 0)
    return com

def closest_point(v, w, p):
    """
    Find the point closest to p on the line between v and w
    Modified from StackOverflow at http://stackoverflow.com/a/1501725

    Returns the distance and the point on the line segment between v and w
    """
    vw = w - v
    len_squared = np.dot(vw, vw)
    if 0. == len_squared:
        # Handles the case when v == w
        projection = v
    else:
        t = max(0., min(1., np.dot((p - v), vw) / len_squared))
        projection = v + t * vw
    return np.linalg.norm(projection - p), projection


import matplotlib.pyplot
from matplotlib.pyplot import *

import numpy
from numpy import linspace, ndarray

import sympy
from sympy import symbols, sympify, solve

# supply & demand functions
p, q = symbols( 'p,q' )
dF = 9 - 0.75*q
sF = 0.75*q

supply_factor = 1000

def get_demand( price ):
	sln = solve( dF - price, q )[ 0 ]

	return round( sln, 2 )

def get_supply( qty ):
	sln = solve( sF - qty, q )[ 0 ] * supply_factor
	return round( sln, 2 )

def graphit():
	len = linspace( 0, 20, 50 )

	figure()

	y = []
	for x in len:
		y.append( dF.subs( { q: x } ) )

	plot( len, y )

	y = []
	for x in len:
		y.append( sF.subs( { q: x } ) )

	plot( len, y )

	legend (('cost','revenue'),loc=2)
	title( 'Breakeven Analysis' )
	show()

if __name__ == '__main__':

	# a
	price = 5.25
	print( 'demand at {0} is {1}.'.format( price, get_demand( price ) ) )

	# b
	print( 'supply at {0}: {1}'.format( price, get_supply( price ) ) )
	price = 3
	print( 'supply at {0}: {1}'.format( price, get_supply( price ) ) )

	# c
	graphit()

import numpy,from numpy,import sympy,from sympy


import numpy as np

def compute_psnr(y_original, y_estimated):
    # COMPUTE_PSNR Computes the PSNR between two images
    #
    # Input:
    #  y_original  - The original image
    #  y_estimated - The estimated image
    #
    # Output:
    #  psnr_val - The Peak Signal to Noise Ratio (PSNR) score

    y_original = np.reshape(y_original, (-1))
    y_estimated = np.reshape(y_estimated, (-1))

    # TODO: Compute the dynamic range
    # Write your code here... dynamic_range = ????
    dynamic_range = y_original.max() - y_original.min()

    # TODO: Compute the Mean Squared Error (MSE)
    # Write your code here... mse_val = ????
    mse_val = np.mean((y_original - y_estimated) ** 2)

    # TODO: Compute the PSNR
    # Write your code here... psnr_val = ????
    psnr_val = 10 * np.log10(dynamic_range ** 2 / mse_val)

    return psnr_val


import numpy as np
import pandas as pd
from scipy import stats

data = pd.read_csv("advertisement_clicks.csv")
X1 = data[data['advertisement_id'] == 'A']
X2 = data[data['advertisement_id'] == 'B']

n1 = X1.shape[0]
n2 = X2.shape[0]
N = n1

x1 = X1['action'].values
x2 = X2['action'].values

t, p = stats.ttest_ind(x1, x2)
print("t:\t", t, "p:\t", 2*p) # two-sided test p-value

t, p = stats.ttest_ind(x1, x2, equal_var=False)
print("Welch's t-test:")
print("t:\t", t, "p:\t", p)


"""
Author: Rahul G. Krishnan
Divergences used between probability measures
"""
import theano.tensor as T
def KLGaussian(mu_1,cov_1,mu_2,cov_2,logCov=False):
    """
    Estimate the KL divergence between two gaussians with diagonal covariance
    KL(q||p)=0.5*(log|Sigma_2|-log|Sigma_1| -D + tr(Sigma_2^-1 Sigma_1) + (mu_2-mu_1)^T Sigma_2^-1 (mu_2-mu_1))
    """
    if type(mu_1) is list:
        assert type(mu_2) is list and type(cov_1) is list and type(cov_2) is list,'Expecting lists'
        div = 0
        for m1,c1,m2,c2 in zip(mu_1,cov_1,mu_2,cov_2):
            div+=KLGaussian(m1,c1,m2,c2,logCov=logCov)
        return div
    else:
        diff   = mu_2-mu_1
        if logCov:
            logcov_1 = cov_1
            logcov_2 = cov_2
            return 0.5*(logcov_2-logcov_1-1+T.exp(logcov_1-logcov_2)+(diff**2)*T.exp(-1*logcov_2)).sum()
        else:
            return 0.5*(T.log(cov_2)-T.log(cov_1)-1+cov_1/cov_2+(diff**2)/cov_2).sum()

def BhattacharryaGaussian(mu_1,cov_1,mu_2,cov_2,logCov=False):
    """
    Estimate the Bhattacharyya distance between two gaussians with diagonal covariance
    D_B(q||p)
    See: http://like.silk.to/studymemo/PropertiesOfMultivariateGaussianFunction.pdf
    https://en.wikipedia.org/wiki/Bhattacharyya_distance
    """
    if type(mu_1) is list:
        assert type(mu_2) is list and type(cov_1) is list and type(cov_2) is list,'Expecting lists'
        div = 0
        for m1,c1,m2,c2 in zip(mu_1,cov_1,mu_2,cov_2):
            div+=BhattacharryaGaussian(m1,c1,m2,c2,logCov=logCov)
        return div
    else:
        diff = mu_1-mu_2
        if logCov:
            logcov_1= cov_1
            logcov_2= cov_2
            P       = (T.exp(logcov_2)+T.exp(logcov_1))/2
            logdet  = T.log(P) - 0.5*(logcov_2+logcov_1)
        else:
            P       = (cov_2+cov_1)/2
            logdet  =T.log(P) -0.5*T.log(cov_2*cov_1)
        D_B  = (1/8.)*(diff**2)/P + (1/2.)*logdet
        return D_B.sum()


"""Clustering-related mathematical functions.
"""

from typing import Optional

import numpy as np

import py4research.math.random as r

def kmeans(x: np.ndarray,
           n_clusters: Optional[int] = 1,
           max_iterations: Optional[int] = 100,
           tol: Optional[float] = 1e-4) -> np.ndarray:
    """Performs the K-Means clustering over the input data.

    Args:
        x: Input array with a shape equal to (n_samples, n_variables, n_dimensions).
        n_clusters: Number of clusters.
        max_iterations: Maximum number of clustering iterations.
        tol: Tolerance value to stop the clustering.

    Returns:
        (np.ndarray): Assigned cluster per input sample.

    """

    # Gathers the corresponding dimensions
    n_samples, n_variables, n_dimensions = x.shape[0], x.shape[1], x.shape[2]

    # Creates an array of centroids and labels
    centroids = np.zeros((n_clusters, n_variables, n_dimensions))
    labels = np.zeros(n_samples)

    for i in range(n_clusters):
        # Chooses a random sample to compose the centroid
        idx = r.generate_integer_random_number(0, n_samples)
        centroids[i] = x[idx]

    for _ in range(max_iterations):
        # Calculates the euclidean distance between samples and each centroid
        dists = np.squeeze(np.array([np.linalg.norm(x - c, axis=1) for c in centroids]))

        # Gathers the minimum distance as the cluster that conquers the sample
        updated_labels = np.squeeze(np.array(np.argmin(dists, axis=0)))

        # Calculates the difference ratio between old and new labels
        ratio = np.sum(labels != updated_labels) / n_samples

        if ratio <= tol:
            break

        # Updates the old labels with the new ones
        labels = updated_labels

        for i in range(n_clusters):
            # Gathers the samples that belongs to current centroid
            centroid_samples = x[labels == i]

            # If there are samples that belongs to the centroid
            if centroid_samples.shape[0] > 0:
                # Updates the centroid position
                centroids[i] = np.mean(centroid_samples, axis=0)

    return labels


import numpy as np

class ShapeFunction:
    """Class which contains functions to calculate the N matrix and the B matrix
    Inputs:
    1) (self.xi, self.eta) = natural coordinates
    2) vertex_coord = coordinates of the vertex points
    3) el_type = type of element used in meshing
       el_type = 0 (4 noded quadrilateral)
       el_type = 1 (8 noded quadrilateral)"""

    def __init__(self, xi, eta, el_type):
        self.xi = xi
        self.eta = eta
        self.el_type = el_type
        if self.el_type == 0:
            self.N = np.zeros((2, 8))
        elif self.el_type == 1:
            self.N = np.zeros((2, 16))
        self.J = np.zeros((2, 2))
        if self.el_type == 0:
            self.dpN = np.zeros((2, 4))
        elif self.el_type == 1:
            self.dpN = np.zeros((2, 8))

    def get_N_matrix(self):
        """Calculate the N matrix"""

        if self.el_type == 0:
            # shape functions for 4 noded quadrilateral
            N1 = (1 - self.xi) * (1 - self.eta) / 4
            N2 = (1 + self.xi) * (1 - self.eta) / 4
            N3 = (1 + self.xi) * (1 + self.eta) / 4
            N4 = (1 - self.xi) * (1 + self.eta) / 4

            self.N[0, ::2] = np.array([N1, N2, N3, N4])
            self.N[1, 1::2] = np.array([N1, N2, N3, N4])
            return self.N

        elif self.el_type == 1:
            # shape function for 8 noded quadrilateral element
            N1 = -(1 - self.xi) * (1 - self.eta)*(1 + self.xi + self.eta) / 4
            N2 = (1 + self.xi) * (1 - self.eta) * (-1 + self.xi - self.eta) / 4
            N3 = (1 + self.xi) * (1 + self.eta) * (-1 + self.xi + self.eta) / 4
            N4 = (1 - self.xi) * (1 + self.eta) * (-1 - self.xi + self.eta) / 4
            N5 = (1 - self.xi ** 2) * (1 - self.eta) / 2
            N6 = (1 + self.xi) * (1 - self.eta ** 2) / 2
            N7 = (1 - self.xi ** 2) * (1 + self.eta) / 2
            N8 = (1 - self.xi) * (1 - self.eta ** 2) / 2

            self.N[0, ::2] = np.array([N1, N2, N3, N4, N5, N6, N7, N8])
            self.N[1, 1::2] = np.array([N1, N2, N3, N4, N5, N6, N7, N8])
            return self.N

    def compute_Jacobian(self, vertex_coord):
        """Calculate the Jacobian matrix for 4 noded and 8 noded quadrilateral element"""

        # dpN = gradient of shape functions wrt natural coordinates (xi, eta)

        if self.el_type == 0:
            self.dpN[0, 0] = -(1 - self.eta) / 4
            self.dpN[1, 0] = -(1 - self.xi) / 4
            self.dpN[0, 1] = (1 - self.eta) / 4
            self.dpN[1, 1] = -(1 + self.xi) / 4
            self.dpN[0, 2] = (1 + self.eta) / 4
            self.dpN[1, 2] = (1 + self.xi) / 4
            self.dpN[0, 3] = -(1 + self.eta) / 4
            self.dpN[1, 3] = (1 - self.xi) / 4

        elif self.el_type == 1:
            self.dpN[0, 0] = -(1-self.eta)*(-2*self.xi-self.eta)/4
            self.dpN[1, 0] = -(1-self.eta)*(-self.xi-2*self.eta)/4
            self.dpN[0, 1] = (1 - self.eta) * (2*self.xi - self.eta) / 4
            self.dpN[1, 1] = -(1 - self.eta) * (-self.xi - 2 * self.eta) / 4
            self.dpN[0, 2] = (1 + self.eta) * (2*self.xi + self.eta) / 4
            self.dpN[1, 2] = (1 + self.eta) * (self.xi + 2 * self.eta) / 4
            self.dpN[0, 3] = (1 + self.eta) * (2*self.xi - self.eta) / 4
            self.dpN[1, 3] = (1 - self.eta) * (-self.xi + 2 * self.eta) / 4
            self.dpN[0, 4] = -2*self.xi * (1- self.eta) / 2
            self.dpN[1, 4] = (-1 + self.xi**2) / 2
            self.dpN[0, 5] = (1- self.eta**2)/2
            self.dpN[1, 5] = -2*self.eta*(1+self.xi) / 2
            self.dpN[0, 6] = -2*self.xi*(1+self.eta) / 2
            self.dpN[1, 6] = (1 - self.xi**2) / 2
            self.dpN[0, 7] = -(1 - self.eta**2) / 2
            self.dpN[1, 7] = (1 - self.xi)*(-2*self.eta) / 2

        self.J = np.dot(self.dpN, vertex_coord)

    def get_B_matrix(self):
        """Calculates the strain displacement matrix (B)"""

        # dN = spatial gradient of shape functions
        dN = np.dot(np.linalg.inv(self.J), self.dpN)
        B = np.zeros((3, 2*self.dpN.shape[1]))

        B[0, ::2] = dN[0, :]
        B[1, 1::2] = dN[1, :]
        B[2, ::2] = dN[1, :]
        B[2, 1::2] = dN[0, :]

        return B


"""
Kindly install these libraries before executing this code:
  1. numpy
  2. matplotlib
  3. scipy
"""

import numpy as np
import matplotlib.pyplot as plt
import cmath
import math
from scipy import stats
from mpl_toolkits.mplot3d.axes3d import Axes3D
from matplotlib import cm
from scipy.stats import multivariate_normal
from mpl_toolkits.mplot3d import Axes3D

# if using a Jupyter notebook, kindly uncomment following line:
%matplotlib inline

def genRandomNumbers(a):
  Z1 = np.random.normal(0, 1, 1000)
  Z2 = np.random.normal(0, 1, 1000)

  X1 = []
  for idx in range(0, len(Z1)):
    X1.append(5 + Z1[idx])

  X2 = []
  for idx in range(0, len(Z1)):
    X2.append(8 + 2*a*Z1[idx] + math.sqrt(1 - a*a)*2*Z2[idx])

  return X1, X2

def plot3D(X1, X2, a):
  x = np.array(X1)
  y = np.array(X2)

  fig = plt.figure()
  ax = fig.add_subplot(111, projection='3d')

  hist, xedges, yedges = np.histogram2d(x, y, bins = (30, 30))
  xpos, ypos = np.meshgrid(xedges[:-1] + xedges[1:], yedges[:-1] + yedges[1:])

  xpos = xpos.flatten()/2.
  ypos = ypos.flatten()/2.
  zpos = np.zeros_like (xpos)

  dx = xedges [1] - xedges [0]
  dy = yedges [1] - yedges [0]
  dz = hist.flatten()

  cmap = cm.get_cmap('jet')
  max_height = np.max(dz)
  min_height = np.min(dz)

  col = [cmap((k-min_height)/max_height) for k in dz]

  ax.bar3d(xpos, ypos, zpos, dx, dy, dz, color = col, zsort = 'average')
  plt.title("Frequency of Generated values for a = {}".format(a))
  plt.xlabel("Z1")
  plt.ylabel("Z2")
  plt.show()

def actualDensity(mu_x, mu_y, variance_x, variance_y, cov):
  x = np.linspace(2, 8, 1000)
  y = np.linspace(2, 14, 1000)
  X, Y = np.meshgrid(x, y)
  pos = np.empty(X.shape + (2,))
  pos[:, :, 0] = X; pos[:, :, 1] = Y
  rv = multivariate_normal([mu_x, mu_y], [[variance_x, cov], [cov, variance_y]])

  fig = plt.figure()
  ax = fig.gca(projection='3d')
  ax.plot_surface(X, Y, rv.pdf(pos), cmap = 'viridis', linewidth = 0)
  ax.set_xlabel('X1')
  ax.set_ylabel('X2')
  ax.set_zlabel('f(X)')
  plt.title('Actual Density for a = {}'.format(cov/2))
  plt.show()

  plt.contour(X, Y, rv.pdf(pos))
  plt.title('Contour plot of Multivariate Normal for a = {}'.format(cov/2))
  plt.xlim([2, 8])
  plt.ylim([3, 13])
  plt.xlabel('X axis')
  plt.ylabel('Y axis')
  plt.show()

def simulatedDensity(X1, X2, a):
  Z = []
  cov = np.array( [[1, 2*a], [2*a, 4]])
  u = np.array([5, 8])
  det = np.linalg.det(cov)

  for idx in range(0, len(X1)):
    x = np.array([X1[idx], X2[idx]])
    Z.append(1/(2*math.pi*math.sqrt(det)) * math.exp(-0.5*np.dot( np.dot(np.transpose(x - u), np.linalg.inv(cov)), (x - u))))

  fig = plt.figure()
  ax = fig.add_subplot(111, projection = '3d')
  ax.scatter(X1, X2, Z)
  ax.set_xlabel('X1')
  ax.set_ylabel('X2')
  ax.set_zlabel('f(X)')
  plt.title('Simulated Density for a = {}'.format(a))
  plt.show()

def marginalDensity(X, mean, var, rho, idx):
  x = np.arange(mean - 5, mean + 5, 0.1)
  y = stats.norm.pdf(x, mean, math.sqrt(var))
  plt.plot(x, y, color = 'red', label = 'Theoretical PDF')

  counts, bin_edges = np.histogram(X, bins = 150, density = 1)
  plt.title('Marginal Density - X{} for a = {}'.format(idx, rho))
  plt.ylabel('f(X)')
  plt.xlabel('X (generated values)')
  plt.plot(bin_edges[1:], counts, color = 'blue', label = "generated PDF")
  plt.legend(loc = "upper left")
  plt.show()

def main():
  a = [-0.5, 0, 0.5, 1]
  num = 1

  for rho in a:
    X1, X2 = genRandomNumbers(rho)
    print('********************** Case {}: a = {} **********************\n'.format(num, rho))
    print('X1 : ')
    print(X1)
    print('Total no of Random numbers in X1 = {}'.format(len(X1)))
    print()
    print('X2 : ')
    print(X2)
    print('Total no of Random numbers in X2 = {}'.format(len(X2)))
    print()

    if rho != 1:
      plot3D(X1, X2, rho)
      simulatedDensity(X1, X2, rho)
      actualDensity(5, 8, 1, 4, 2*rho)

    marginalDensity(X1, 5, 1, rho, 1)
    marginalDensity(X2, 8, 4, rho, 2)
    num += 1

if __name__ == "__main__":
    main()


import numpy as np

from frccontrol.numerical_jacobian import *

def test_numerical_jacobian():
    A = np.array([[1, 2, 4, 1], [5, 2, 3, 4], [5, 1, 3, 2], [1, 1, 3, 7]])
    B = np.array([[1, 1], [2, 1], [3, 2], [3, 7]])

    def AxBuFn(x, u):
        return A @ x + B @ u

    newA = numerical_jacobian_x(4, 4, AxBuFn, np.zeros((4, 1)), np.zeros((2, 1)))
    assert np.allclose(A, newA)

    newB = numerical_jacobian_u(4, 2, AxBuFn, np.zeros((4, 1)), np.zeros((2, 1)))
    assert np.allclose(B, newB)


import numpy as np
import matplotlib.pyplot as plt

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

def stable_coeff(alpha_1, alpha_2):
    a_1 = 2*np.tanh(alpha_1)
    a_2 = np.abs(a_1) + (2 - np.abs(a_1))*sigmoid(alpha_2) - 1
    return a_1, a_2

def roots_polynomial(a_1, a_2):
    delta = a_1**2 - 4 * a_2
    delta = delta.astype(np.complex)
    root_1 = (-a_1 + np.sqrt(delta))/2
    root_2 = (-a_1 - np.sqrt(delta))/2
    idx_real = delta > 0
    return root_1, root_2, idx_real

if __name__ == '__main__':

    N = 10000
    alpha_1 = np.random.randn(N)*1
    alpha_2 = np.random.randn(N)*1

    a_1, a_2 = stable_coeff(alpha_1, alpha_2)
    r_1, r_2, idx_real = roots_polynomial(a_1, a_2)

    fig, ax = plt.subplots()
    ax.plot(a_1, a_2, '*')
    ax.plot(a_1[idx_real], a_2[idx_real], 'k*')
    ax.set_xlabel('a_1')
    ax.set_ylabel('a_2')
    ax.set_xlim([-2, 2])
    ax.set_ylim([-2, 2])

    fig, ax = plt.subplots()
    ax.plot(np.real(r_1), np.imag(r_1), 'r*')
    ax.plot(np.real(r_2), np.imag(r_2), 'r*')
    ax.plot(np.real(r_1)[idx_real], np.imag(r_1)[idx_real], 'k*')
    ax.plot(np.real(r_2)[idx_real], np.imag(r_2)[idx_real], 'k*')
    ax.set_xlim([-1.2, 1.2])
    ax.set_ylim([-1.2, 1.2])

    perc_real = np.sum(idx_real) / N *100
    print(f"Real poles in {perc_real:.1f} cases")


import numpy as np

def Gini_index(Y_data):
    gini = 0
    #=========    Edit here    ==========
    #
    myset = list(set(Y_data))
    plist = [0]*len(myset)

    for y in Y_data:
        for s in myset:
            if y == s:
                plist[myset.index(s)] += 1

    for i in range(len(plist)):
        plist[i] /= len(Y_data)
        if plist[i] == 0:
            continue
        gini += plist[i]*(1-plist[i])

    #
    #
    #====================================
    return gini

def Entropy(Y_data):

    entropy = 0
    # =====    Edit here    ========
    #
    myset = list(set(Y_data))
    plist = [0]*len(myset)

    for y in Y_data:
        for s in myset:
            if y == s:
                plist[myset.index(s)] += 1
    for i in range(len(plist)):
        plist[i] /= len(Y_data)
        if plist[i] == 0:
            continue
        entropy -= plist[i]*np.log2(plist[i])

    #
    #
    # ==============================
    return entropy

def impurity_func(Y_data, criterion):

    if criterion == 'gini':
        return Gini_index(Y_data)

    elif criterion == 'entropy':
        return Entropy(Y_data)

def Finding_split_point(df, feature, criterion):

    col_data = df[feature]
    Y = df.values[:, -1]
    distinct_data = np.unique(col_data)

    split_point = distinct_data[0]
    min_purity = 1

    for idx, val in enumerate(distinct_data):
        less_idx = (col_data < val)

        y0 = Y[less_idx]
        y1 = Y[~less_idx]

        p0 = len(y0) / len(Y)
        p1 = len(y1) / len(Y)

        purity = np.sum([p0 * impurity_func(y0, criterion), p1 * impurity_func(y1, criterion)])

        if min_purity > purity:
            min_purity = purity
            split_point = val

    return split_point

def Gaussian_prob(x, mean, std):
    '''
    :param x: input value: X
    :param mean: the mean of X
    :param std: the standard deviation of X
    :return: probaility (X) ~ N(μ, σ^2)
    '''
    ret = 0
    # ========      Edit here         ==========
    pi = np.pi
    e = np.e
    ret = 1/((2*pi*std)**(1/2)) * (np.e)**((-1)*(x-mean)**2/(2*std))
    # =========================================
    return ret


import scipy
import scipy.stats
import numpy as np
from scipy.stats import pearsonr

def mean_confidence_interval(data, confidence=0.95):
    '''
    Return confidence interval from list.

    Args:
        data (np.ndarray or list) : the list
        confidence (float) : the confidence interval to calculate 0.95 for 95%
    '''
    data = np.array(data)
    data = data[~np.isnan(data)]
    a = 1.0 * data
    n = len(a)
    m, se = np.mean(a), scipy.stats.sem(a)
    h = se * scipy.stats.t.ppf((1 + confidence) / 2., n-1)
    return m, m-h, m+h

def get_pearsonr(a, b):
    '''
    Return Pearson correlation coefficient given 2 arrays
    '''
    return pearsonr(a, b)


#!/usr/bin/env python
"""stats_binom.py: Demonstrate how ``scipy.stats.binom`` works.
"""
from scipy.stats import binom

# pylint: disable=invalid-name

N = 6
p = 0.25
rv = binom(N, p)

# Compute moments.
mean, var, skew, kurt = rv.stats(moments='mvsk')

# mean == N * p
print(f"mean: {float(mean):.3f}")

# median == np.floor(N * p) or np.ceil(N * p) ?
print(f"median: {rv.median():.3f}")

# var == N * p * (1 - p)
print(f"var: {float(var):.3f}")

# skew == (1 - 2 * p)/np.sqrt(N * p * (1 - p))
print(f"skew: {float(skew):.3f}")

# kurt == (1 - 6 * p * (1 - p))/(N * p * (1 - p))
print(f"kurt: {float(kurt):.3f}")

# std == np.sqrt(var)
print(f"std: {rv.std():.3f}")

print("How many times you win:")
for i in range(N + 1):
    print(f"{i}/{N}: {float(rv.pmf(i)):.8f}")


"""
Unit-tests for the S-shaped mappings

Author: Patrick Henriksen <patrick@henriksen.as>
"""

import unittest
import numpy as np

from src.algorithm.mappings.s_shaped import Sigmoid, Tanh

class TestMappingSShaped(unittest.TestCase):

    def setUp(self):

        self.sigmoid = Sigmoid()
        self.tanh = Tanh()

    @staticmethod
    def s(x):
        """
        Sigmoid function used for calculating ground trouth values.
        """

        return 1/(1 + np.exp(-x))

    def test_sigmoid_properties(self):
        """
        Test the return values of is_linear() and is_1d_to_1d().
        """

        self.assertTrue(self.sigmoid.is_1d_to_1d)
        self.assertFalse(self.sigmoid.is_linear)

    def test_sigmoid_propagate_float(self):
        """
        Test the propagate() method with floats.
        """

        x0, x1 = 2.5, -2.5

        self.assertAlmostEqual(self.sigmoid.propagate(x0), self.s(x0))
        self.assertAlmostEqual(self.sigmoid.propagate(x1), self.s(x1))

    def test_sigmoid_propagate_array(self):
        """
        Test the propagate() method with arrays.
        """

        x = np.array([2.5, -2.5])
        res = self.sigmoid.propagate(x)

        self.assertAlmostEqual(res[0], self.s(x[0]))
        self.assertAlmostEqual(res[1], self.s(x[1]))

    def test_sigmoid_linear_relaxation(self):
        """
        Test the linear_relaxation() for positive, negative and mixed bounds.
        """

        # Test intercepting line

        bounds = np.array([[-2.5, -1]])
        relax = self.sigmoid.linear_relaxation(bounds[:, 0], bounds[:, 1], upper=True)
        gt_a = (self.s(bounds[0, 1]) - self.s(bounds[0, 0]))/(bounds[0, 1] - bounds[0, 0])
        gt_b = self.s(bounds[0, 1]) - (gt_a * bounds[0, 1])
        self.assertAlmostEqual(relax[0, 0], gt_a)
        self.assertAlmostEqual(relax[0, 1], gt_b)

        # Test optimal tangent:

        bounds = np.array([[0, 2.5]])
        relax = self.sigmoid.linear_relaxation(bounds[:, 0], bounds[:, 1], upper=True)
        tangent_point = ((bounds[:, 1]**2 - bounds[:, 0]**2)/(2*(bounds[:, 1] - bounds[:, 0])))[0]
        gt_a = self.s(tangent_point) * (1-self.s(tangent_point))
        gt_b = self.s(tangent_point) - (gt_a * tangent_point)

        self.assertAlmostEqual(relax[0, 0], gt_a)
        self.assertAlmostEqual(relax[0, 1], gt_b)

    def test_sigmoid_split_point(self):
        """
        Test the split_point() method.
        """

        split_point = self.sigmoid.split_point(-2.5, 2)
        mid = (self.s(2) + self.s(-2.5)) / 2
        self.assertAlmostEqual(split_point, -np.log((1 / mid) - 1))

    def test_tanh_properties(self):
        """
        Test the return values of is_linear() and is_1d_to_1d().
        """

        self.assertTrue(self.tanh.is_1d_to_1d)
        self.assertFalse(self.tanh.is_linear)

    def test_tanh_propagate_float(self):
        """
        Test the propagate() method with floats.
        """

        x0, x1 = 2.5, -2.5

        self.assertAlmostEqual(self.tanh.propagate(x0), np.tanh(x0))
        self.assertAlmostEqual(self.tanh.propagate(x1), np.tanh(x1))

    def test_tanh_propagate_array(self):
        """
        Test the propagate() method with arrays.
        """

        x = np.array([2.5, -2.5])
        res = self.tanh.propagate(x)

        self.assertAlmostEqual(res[0], np.tanh(x[0]))
        self.assertAlmostEqual(res[1], np.tanh(x[1]))

    def test_tanh_linear_relaxation(self):
        """
        Test the linear_relaxation() for positive, negative and mixed bounds.
        """

        # Test intercepting line

        bounds = np.array([[-2.5, -1]])
        relax = self.tanh.linear_relaxation(bounds[:, 0], bounds[:, 1], upper=True)
        gt_a = (np.tanh(bounds[0, 1]) - np.tanh(bounds[0, 0]))/(bounds[0, 1] - bounds[0, 0])
        gt_b = np.tanh(bounds[0, 1]) - (gt_a * bounds[0, 1])
        self.assertAlmostEqual(relax[0, 0], gt_a)
        self.assertAlmostEqual(relax[0, 1], gt_b)

        # Test optimal tangent:

        bounds = np.array([[0, 2.5]])
        relax = self.tanh.linear_relaxation(bounds[:, 0], bounds[:, 1], upper=True)
        tangent_point = ((bounds[:, 1]**2 - bounds[:, 0]**2)/(2*(bounds[:, 1] - bounds[:, 0])))[0]
        gt_a = 1 - np.tanh(tangent_point)**2
        gt_b = np.tanh(tangent_point) - (gt_a * tangent_point)

        self.assertAlmostEqual(relax[0, 0], gt_a)
        self.assertAlmostEqual(relax[0, 1], gt_b)

    def test_tanh_split_point(self):
        """
        Test the split_point() method.
        """

        split_point = self.tanh.split_point(-2.5, 2)

        mid = (np.tanh(2) + np.tanh(-2.5)) / 2
        self.assertAlmostEqual(split_point, 0.5 * np.log((1 + mid) / (1 - mid)))


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

epsilon = np.exp(-5)

# load the data and make the mean zero
x = np.loadtxt('/home/akhi/progs/pcaData.txt')
plt.figure(1)
plt.scatter(x[0,:], x[1,:])

avg = np.mean(x, 0)
x = x - np.matlib.repmat(avg, 2, 1)

"""compute covariance matrix, and then eigen values and eigen vectors of covariance
matrix using singular value decomposition"""
sigma = np.dot(x, np.transpose(x)) / x.shape[1]
U, S, V = np.linalg.svd(sigma) #np.dot(np.dot(U,np.diag(S)),V) gives the sigma back

#plot eigne vectors and verirfy their direction
plt.plot([0, U[0,0]],[0, U[1,0]])
plt.plot([0, U[0,1]],[0, U[1,1]])
plt.show()

"""compute the transformation to the new basis U
we can choose to retain k components in this stage"""
xRot = np.dot(np.transpose(U), x) # U'*x;
xTilde = np.dot(np.transpose(U[:,0:1]), x) # retains only one component

#PCA whitening
plt.figure(2)
xPCAWhite =  np.dot(np.diag(1 / np.sqrt(S + epsilon)), xRot)
# scale xPCAWhite[1](2nd row) with 1e+34 to get the same plot as in matlab,
# since the range of values is very small. if you didn't scale python will
# apptoximate it to xero and you will get a straight line parallel to x - axis
xPCAWhite[1] = xPCAWhite[1] * np.exp(34)
plt.scatter(xPCAWhite[0,:], xPCAWhite[1,:])
plt.show()

#ZCA whitening
plt.figure(3)
xZCAWhite = np.dot(U, xPCAWhite)
plt.scatter(xZCAWhite[0,:], xZCAWhite[1,:])
plt.show()


'''
Library of functions for Neural Networks
'''
import numpy as np

"""
Implements the gradient of the squared loss function
Parameters:
    -output_activations: a numpy ndarray of shape (2,1) containing the values of the output layer
    -y: a numpy ndarray of shape (2,1) containing the correct values for the output layer

Returns:
    a float value representing the gradient of the error with respect to the value of the output
    activations. This should be a numpy ndarray with the same shape as the inputs
"""
def squared_loss_gradient (output_activations, y):
    return - y + output_activations
    # return np.zeros((2,1))
#endDef

def sigmoid (z):
    return 1.0/(1.0 + np.exp(-z))
#endDef

def sigmoid_derivative (z):
    return sigmoid(z) * (1-sigmoid(z))
#endDef

def relu (z):
    return np.maximum(0, z)
#endDef

"""
Implements the derivative of the relu function, evaluated element-wise over the input vector
Parameters:
    -z: a numpy nd-array containing the output values of a layer of the neural network

Returns:
    a numpy nd-array having the same shape as the input where each index represents the derivative
    of the relu function applied to the corresponding coordinate of the input
"""
def relu_derivative (z):
    z[z > 0] = 1
    z[z <= 0] = 0
    return z
    # return np.zeros(z.shape)
#endDef

def tanh (z):
    return (np.exp(z) - np.exp(-z)) / (np.exp(z) + np.exp(-z))
#endDef

def tanh_derivative (z):
    return np.ones(z.shape) - np.square(tanh(z))
#endDef


#!/usr/bin/env python3
"""
Markov Module
"""
import numpy as np

def regular(P):
    """
    Determines the steady state probabilities of a regular markov chain:

    P is a is a square 2D numpy.ndarray of shape (n, n) representing the
    transition matrix
        P[i, j] is the probability of transitioning from state i to state j
        n is the number of states in the markov chain

    Returns: a numpy.ndarray of shape (1, n) containing the steady state
    probabilities, or None on failure
    """
    if type(P) is not np.ndarray or len(P.shape) != 2:
        return None
    if P.shape[0] != P.shape[1]:
        return None
    if np.sum(P, axis=1).all() != 1:
        return None

    s = np.ones((1, P.shape[0])) / P.shape[0]
    Ps = P.copy()
    while True:
        sprv = s
        s = np.matmul(s, P)
        Ps = P * Ps
        if np.any(Ps <= 0):
            return (None)
        if np.all(sprv == s):
            return (s)


import numpy as np
from numpy import cos, sin, pi, exp, log

#takes a vector [w] and returns the corresponding 3x3 skew symmetric matrix W
#such that for any other vector v, we have (w x v) = W.v
def to_skew(w):
    return np.array([[0, -w[2], w[1]],[w[2],0,-w[0]],[-w[1], w[0],0]])

#rotation around x (Returns 3x3 matrix)
def Rx(th):
    return np.array([[1,0,0],
                     [0,cos(th),-sin(th)],
                     [0,sin(th), cos(th)]])

#rotation around y (returns 3x3 matrix)
def Ry(th):
    return np.array([[cos(th), 0, sin(th)],
                    [0,1,0],
                    [-sin(th),0,cos(th)]])

#rotation around z (returns 3x3 matrix)
def Rz(th):
    return np.array([[cos(th), -sin(th), 0],
                     [sin(th),cos(th),0],
                     [0,0,1]])

#exponential map from [w] to 3x3 rotation matrix
def R_exp(w):
    w_hat = to_skew(w)
    norm = np.linalg.norm(w)
    if(norm > 0.001):
        return np.eye(3) + w_hat /norm * sin(norm) + w_hat.dot(w_hat)/(norm**2)*(1-cos(norm))
    else:
        return np.eye(3)

#exponential map from [v,w] to 4x4 homogenous transform
def T_exp(v,w):
    R = R_exp(w)
    T = np.eye(4)
    if(np.linalg.norm(w)<0.001):
        T[0:3,3] = v
    else:
        w_hat = to_skew(w)
        w_norm = np.linalg.norm(w)
        A = np.eye(3) + (1 - cos(w_norm))/(w_norm**2) * w_hat + (w_norm - sin(w_norm))/(w_norm**3) * w_hat.dot(w_hat)
        t = A.dot(v)
        T[0:3,0:3] = R
        T[0:3,3] = t
    return T

def hom(R,p):
    T = np.identity(4)
    T[0:3,0:3] = R
    T[0:3,3] = p
    return T

#returns the adjoint of homogeneous transform T
def adjoint(T):
    ad = np.zeros([6,6])
    ad[0:3,0:3] = T[0:3,0:3]
    ad[3:6,3:6] = T[0:3,0:3]
    ad[3:6,0:3] = to_skew(T[0:3,3]).dot(T[0:3,0:3])
    return ad


import numpy as np
import matplotlib.pyplot as plt

def knot_pad(Xi,p):
    """
    Repeats first and last knots of Xi
    """
    # Check on types
    assert isinstance(Xi,np.ndarray)
    # Pad knot vector with due repretitions
    return np.hstack((np.ones([p]) * Xi[0], Xi, np.ones([p]) * Xi[-1]))

def bspline(i, p, Xi, s):
    """
    Evaluation of univariate B-Splines by Cox-DeBoor recursion

    i: index of the B-spline
    p: B-spline degree
    Xi: knot vector
    s: evaluation point

    [1] Cox, M. G. (Oct. 1972). “The numerical evaluation of B-splines”. In: Journal of
        the Institute of Mathematics and its Applications 10.2, pp. 134–149. ISSN:
        0020-2932.
    [2] De Boor, C. (1972). “On calculating with B-splines”. In: Journal of
        Approximation Theory 6. Collection of articles dedicated to J. L. Walsh on
        his 75th birthday, V (Proc. Internat. Conf. Approximation Theory, Related
        Topics and their Applications, Univ. Maryland, College Park, Md., 1970),
        pp. 50–62. ISSN: 0021-9045.
    """

    # Check types
    assert isinstance(i,int)
    assert isinstance(p,int)
    assert isinstance(Xi,np.ndarray)

    # Initialize output to zero
    b = np.zeros(np.shape(s))

    # Define degree zero
    if p==0:
        if Xi[i+1] < Xi[-1]:
            # Internal nodes
            b[(Xi[i] <= s) & (s < Xi[i+1])] = 1
        else:
            # Last subinterval
            b[(Xi[i] <= s) & (s <= Xi[-1])] = 1
    else:
        d = Xi[i+p]-Xi[i] # side sx
        if d > 0:
            b = b + (s - Xi[i]) * bspline(i,p-1,Xi,s)/d

        d = Xi[i+p+1]-Xi[i+1] # side dx
        if d > 0:
            b = b + (Xi[i+p+1] - s) * bspline(i+1,p-1,Xi,s)/d

    return b

def bspline_space_dim(p,Xi):
    """
    Computes dimension of B-spline space span
    """
    assert isinstance(p,int)
    assert isinstance(Xi,np.ndarray)

    return np.size(Xi) - p - 1

def plot_bspline_basis(p,Xi):
    """
    Plots all B-spline basis functions
    """
    assert isinstance(p,int)
    assert isinstance(Xi,np.ndarray)

    # Evaluation points
    x = np.linspace(Xi[0],Xi[-1],20*np.size(Xi))

    for fdx in range(0,bspline_space_dim(p,Xi)):
        plt.plot(x,bspline(fdx,p,Xi,x))

    plt.show()

p = 6
# Xi = np.linspace(0, 1, 5)
Xi = np.sort(np.random.rand(5))
Xi = knot_pad(Xi,p)

# plot_bspline_basis(p,Xi)


#!/usr/bin/env python
# Exercises using automatic differentiation

import torch
import numpy as np

# x = torch.Tensor([1, 2], requires_grad=True)

def g(x):
    return 2 * x + 1

def f(x):
    return x ** 2

x = torch.tensor([1.], requires_grad=True)
y = f(g(x))

x.grad # gradient hasn't appeared yet
y.backward()
# to evaluate at x = 0,
# y.backward(torch.tensor([0.]))
# can specify any values at input at which to take gradient

print(x.grad) ## dy / dx

# what about multidimensional inputs?
def g(x):
    return x[0] + 2 * x[1]

def f(x):
    return torch.sqrt(x)

x = torch.tensor([0., 1.], requires_grad=True)
y = f(g(x))

y.backward()
print(x.grad)

# This example is still simple enough that you can check it by hand
#
# (x0 + 2x1) ** (1/2)
# 1/2 * (x0 + 2x1) ^ (-1/2) . (1, 2)^T
# at [0, 1] this is [1/(2 * sqrt(2)) and 2/(2 * sqrt(2))]
# check that this is correct

# can even do crazy relu stuff (y = sigma(W * x))
def g(x):
    W = torch.randn((10, 10))
    return W.mm(x)

def f(x):
    return torch.clamp(x, min=0)

def h(x):
    return torch.sum(x)

x = torch.randn((10, 1), requires_grad=True)
y = h(f(g(x)))

y.backward()
print(x.grad)

# In theory, you could use these gradients to do neural network optimization by
# yourself, without ever referencing the optim class in pytorch


import numpy as np
import sympy
from sympy import cos, sin, sinh

from einsteinpy.symbolic import (
    MetricTensor,
    RicciScalar,
    RicciTensor,
    RiemannCurvatureTensor,
)

def spherical_metric():
    symbolstr = "r theta phi"
    syms = sympy.symbols(symbolstr)
    list2d = (np.zeros(shape=(3, 3), dtype=int)).tolist()
    list2d[0][0] = 1
    list2d[1][1] = syms[0] ** 2
    list2d[2][2] = (syms[0] ** 2) * (sympy.sin(syms[1]) ** 2)
    metric = MetricTensor(list2d, syms)
    return metric

def anti_de_sitter_metric():
    coords = sympy.symbols("t chi theta phi")
    t, ch, th, ph = coords
    m = sympy.diag(
        -1,
        cos(t) ** 2,
        cos(t) ** 2 * sinh(ch) ** 2,
        cos(t) ** 2 * sinh(ch) ** 2 * sin(th) ** 2,
    ).tolist()
    metric = MetricTensor(m, coords)
    return metric

def test_Ricci_is_zero_for_spherical_space():
    metric = spherical_metric()
    dims = metric.dims
    T = RicciTensor.from_metric(metric)
    arr = T.tensor()
    for i in range(dims ** 2):
        n = i % dims
        r = (int(i / dims)) % (dims)
        assert sympy.simplify(arr[n, r]) == 0

def test_TypeError():
    testarr = np.ones((4, 4), dtype=int).tolist()
    syms = 0
    try:
        obj = RicciTensor(testarr, syms)
        assert False
    except TypeError:
        assert True

def test_RicciTensor_parent_metric_property_and_ValueError():
    mt = anti_de_sitter_metric()
    Rt = RicciTensor.from_metric(mt)
    assert Rt.parent_metric == Rt._parent_metric and Rt.parent_metric == mt
    # ValueError test part
    try:
        Rt2 = RicciTensor(Rt.tensor(), Rt.syms, config="uuu")
        assert False
    except ValueError:
        assert True

def test_RicciTensor_from_riemann_with_arbritary_config():
    mt = anti_de_sitter_metric()
    rm = RiemannCurvatureTensor.from_metric(mt)
    rm2 = rm.change_config("lulu")
    try:
        Rt = RicciTensor.from_riemann(rm2)
        assert True
    except Exception:
        assert False

# Tests for Ricci Scalar

def test_RicciScalar_is_constant_for_ADS_spacetime():
    # R is -12 for anti-de-Sitter spacetime
    mt = anti_de_sitter_metric()
    R = RicciScalar.from_metric(mt)
    assert sympy.simplify(R._expr).is_constant()

def test_RicciScalar_expr_property():
    x, y = sympy.symbols("x y")
    R = RicciScalar(x ** 2 * y * 3, (x, y))
    assert sympy.simplify(R._expr - R.expr) == 0

def test_RicciScalar_raise_TypeError():
    x, y = sympy.symbols("x y")
    try:
        R = RicciScalar(x ** 2 * y * 3, 0)
        assert False
    except TypeError:
        assert True


import numpy as np
import math
import matplotlib.pyplot as plt
from scipy.stats import norm
from scipy.stats import invgamma
from scipy.stats import gaussian_kde

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

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

def sweep(sigma2, mu_0, sigma2_0, alpha, beta, data):
    posterior_mean, posterior_variance = mean_posterior(
        data, mu_0, sigma2_0, sigma2)
    mu = norm.rvs(posterior_mean, scale=np.sqrt(posterior_variance))
    posterior_alpha, posterior_beta = variance_posterior(data, alpha, beta, mu)
    sigma2 = invgamma.rvs(posterior_alpha, scale=posterior_beta)
    return mu, sigma2

def gibbs(data, sigma2, mu_0, sigma2_0, alpha, beta, n_samples=1000):
    mu_samples = np.zeros(n_samples)
    sigma2_samples = np.zeros(n_samples)
    for i in xrange(n_samples):
        mu, sigma2 = sweep(sigma2, mu_0, sigma2_0, alpha, beta, data)
        mu_samples[i] = mu
        sigma2_samples[i] = sigma2
    return mu_samples, sigma2_samples


import numpy as np
#import numba as nb
import math as mp

#spec = [
#(('x', nb.float64[:, :])          # an array field
#)
#    ]

#@nb.jit(parallel=True)
def himmelblau(x: np.array) -> np.float:
    """
    https://en.wikipedia.org/wiki/Himmelblau%27s_function
    f(3,2)=0
    f(-2.8051, 3.1313)=0
    f(-3.7793,-3.2831)=0
    f(3.5844, -1.8481)=0
    """
    __name__  = 'Himmelblau'
    f = (((x[0]**2) + x[1] - 11)**2) + ((x[0] + x[1]**2) - 7)**2
    assert(type(f) != float)
    return f

def ackley(x: np.array) -> np.float:
    """
    f(0,0)=0
    """
    __name__  = 'Ackley'
    f = -20*np.exp(-0.2*np.sqrt(0.5*(x[0]**2+x[1]**2))) - np.exp(0.5*(np.cos(2*np.pi*x[0]) + np.cos(2*np.pi*x[1])) ) + np.e + 20
    return f


import numpy as np

from Losses import Loss

class GeometricMeanRelativeAbsoluteError(Loss):
    def call(self, true_labels, predicted_labels):
        result = np.abs(true_labels - predicted_labels) / np.abs(true_labels - np.mean(true_labels))

        return np.power(np.prod(result), (1 / true_labels.shape[0]))

    def __call__(self, true_labels, predicted_labels):
        return self.call(true_labels, predicted_labels)


import setup
setup.deal_with_path()

import numpy as np
import scipy.linalg
import math
from timeit import default_timer as timer
import linreg_qr
import linreg_setup

def solve_weights_numpy_least_square(X, Y):
    features = np.append(X, np.ones([X.shape[0], 1]), axis=1)
    t0 = timer()
    weights = np.linalg.lstsq(features, Y, rcond=None)[0]
    print("Numpy least square: ", timer()-t0, "s")
    print("Numpy least square residule: ", np.linalg.norm(np.matmul(features, weights)-Y)/math.sqrt(features.shape[0]))
    print("")
    return weights

def solve_weights_qr(X, Y, colTrunc=False):
    features = np.append(X, np.ones([X.shape[0], 1]), axis=1)
    t = 0
    if not colTrunc:
        t0 = timer()
        q, r = np.linalg.qr(features)
        tDecomp = timer()-t0
        t += tDecomp
    else:
        t0 = timer()
        q, r, p = scipy.linalg.qr(features, mode='economic', pivoting=True)
        tDecomp = timer()-t0
        t += tDecomp
    t0 = timer()
    qtY = np.matmul(q.T, Y)
    tQtY = timer()-t0
    t += tQtY
    if not colTrunc:
        t0 = timer()
        weights = np.linalg.solve(r, qtY)
        tBS = timer()-t0
        t += tBS
    else:
        t0 = timer()
        weights = np.linalg.solve(r, qtY)
        invp = np.empty_like(p)
        invp[p] = np.arange(0, features.shape[1])
        weights[:, 0] = weights[invp, 0]
        tBS = timer()-t0
        t += tBS
    if not colTrunc:
        print("Numpy QR: ", t, "s")
    else:
        print("Scipy QR: ", t, "s")
    print("\tDecomposition: ", tDecomp, "s")
    print("\tApply Q: ", tQtY, "s")
    print("\tBacksolve: ", tBS, "s")
    print("QR residual: ", np.linalg.norm(np.matmul(features, weights)-Y)/math.sqrt(features.shape[0]))
    print("")
    return weights

def solve_weights_federated_qr_householder(X, Y, nFeatures, clientIdWLabel, encryLv=3, weightsExact=np.nan, colTrunc=False):
    features = np.append(X, np.ones([X.shape[0], 1]), axis=1)
    clientMap, coordinator = linreg_setup.setup_problem(X, Y, nFeatures, clientIdWLabel, qrMthd="HouseHolder", colTrunc=colTrunc)
    t = 0
    t0 = timer()
    linreg_qr.preprocessing_wo_constaint(clientMap, coordinator.machine_info_client, encryLv)
    tPreprocess = timer()-t0
    t += tPreprocess
    t0 = timer()
    linreg_qr.compute_qr_householder_unencrypted(clientMap, coordinator.machine_info_client)
    tDecomp = timer()-t0
    t += tDecomp
    t0 = timer()
    linreg_qr.apply_householder_unencrypted(clientMap, coordinator.machine_info_client)
    tQtY = timer()-t0
    t += tQtY
    t0 = timer()
    weights = linreg_qr.apply_back_solve_wo_constraint(clientMap, coordinator.machine_info_client)
    tBS = timer()-t0
    t += tBS
    print("Federated QR using HouseHolder reflection: ", t, "s")
    print("\tPreprocessing: ", tPreprocess, "s")
    print("\tDecomposition: ", tDecomp, "s")
    print("\tApply Q: ", tQtY, "s")
    print("\tBacksolve and postprocessing: ", tBS, "s")
    if np.isscalar(weightsExact) and np.isnan(weightsExact):
        features = np.append(X, np.ones([X.shape[0], 1]), axis=1)
        weightsExact = np.linalg.lstsq(features, Y, rcond=None)[0]
    err = weights - weightsExact
    print("Relative error based on inf-norm: ", np.linalg.norm(err, np.inf)/np.linalg.norm(weightsExact, np.inf))
    print("Relative error based on 2-norm: ", np.linalg.norm(err)/np.linalg.norm(weightsExact))
    print("Federated QR residual: ", np.linalg.norm(np.matmul(features, weights)-Y)/math.sqrt(features.shape[0]))
    print("")
    return weights

def solve_weights_federated_qr_gramschmidt(X, Y, nFeatures, clientIdWLabel, encryLv=3, weightsExact=np.nan, colTrunc=False):
    features = np.append(X, np.ones([X.shape[0], 1]), axis=1)
    clientMap, coordinator = linreg_setup.setup_problem(X, Y, nFeatures, clientIdWLabel, qrMthd="GramSchmidt", colTrunc=colTrunc)
    t = 0
    t0 = timer()
    linreg_qr.preprocessing_wo_constaint(clientMap, coordinator.machine_info_client, encryLv)
    tPreprocess = timer()-t0
    t += tPreprocess
    t0 = timer()
    linreg_qr.compute_qr_gramschmidt_unencrypted(clientMap, coordinator.machine_info_client)
    tDecomp = timer()-t0
    t += tDecomp
    t0 = timer()
    linreg_qr.apply_q_unencrypted(clientMap, coordinator.machine_info_client)
    tQtY = timer()-t0
    t += tQtY
    t0 = timer()
    weights = linreg_qr.apply_back_solve_wo_constraint(clientMap, coordinator.machine_info_client)
    tBS = timer()-t0
    t += tBS
    print("Federated QR using Gram-Schmidt method: ", t, "s")
    print("\tPreprocessing: ", tPreprocess, "s")
    print("\tDecomposition: ", tDecomp, "s")
    print("\tApply Q: ", tQtY, "s")
    print("\tBacksolve and postprocessing: ", tBS, "s")
    if np.isscalar(weightsExact) and np.isnan(weightsExact):
        features = np.append(X, np.ones([X.shape[0], 1]), axis=1)
        weightsExact = np.linalg.lstsq(features, Y, rcond=None)[0]
    err = weights - weightsExact
    print("Relative error based on inf-norm: ", np.linalg.norm(err, np.inf)/np.linalg.norm(weightsExact, np.inf))
    print("Relative error based on 2-norm: ", np.linalg.norm(err)/np.linalg.norm(weightsExact))
    print("Federated QR residual: ", np.linalg.norm(np.matmul(features, weights)-Y)/math.sqrt(features.shape[0]))
    print("")
    return weights

def solve_weights_federated_qr(X, Y, nFeatures, clientIdWLabel, qrMthd, encryLv=3, weightExact=np.nan, colTrunc=False):
    if qrMthd=="HouseHolder":
        weights = solve_weights_federated_qr_householder(X, Y, nFeatures, clientIdWLabel, encryLv, weightExact, colTrunc)
    elif qrMthd=="GramSchmidt":
        weights = solve_weights_federated_qr_gramschmidt(X, Y, nFeatures, clientIdWLabel, encryLv, weightExact, colTrunc)
    else:
        raise RuntimeError("QR by the specific method is not implemented yet.")
    return weights

def demo_performance_qr(qrMthd="HouseHolder"):
    print("*"*120)
    print("Demonstrate the performance of federated QR implemented by ", qrMthd, " method")
    dataMax = 10**4
    print("The features are generated with variate scales. The largest scale is ", dataMax)
    print("The label values are generated by adding the multiplication of the features and some random generated weights with some perturbation")
    clientIdWLabel = 1
    print("The label is kept by beh second client")

    print("="*60)
    print("Problem1: Performance on small scale problem without column truncation")
    nSample = 1000
    nFeatures = [3, 3, 5, 11, 8]
    colTrunc = False
    print("The test data are generated randomly and consist of ", nSample, " samples and ", sum(nFeatures), " features")
    encryLv = 3
    XTrain, YTrain, XInfer = linreg_setup.generate_fullrank_test_data(nSample, 0, nFeatures, dataMax)
    weightsExact = solve_weights_numpy_least_square(XTrain, YTrain)
    solve_weights_qr(XTrain, YTrain, colTrunc)
    solve_weights_federated_qr(XTrain, YTrain, nFeatures, clientIdWLabel, qrMthd, encryLv, weightsExact, colTrunc)

    print("="*60)
    print("Problem2: Performance on large scale problem without column truncation")
    nSample = 1000000
    nFeatures = [40, 20, 30, 100, 10]
    colTrunc = False
    print("The test data are generated randomly and consist of ", nSample, " samples and ", sum(nFeatures), " features")
    encryLv = 3
    XTrain, YTrain, XInfer = linreg_setup.generate_fullrank_test_data(nSample, 0, nFeatures, dataMax)
    weightsExact = solve_weights_numpy_least_square(XTrain, YTrain)
    solve_weights_qr(XTrain, YTrain, colTrunc)
    solve_weights_federated_qr(XTrain, YTrain, nFeatures, clientIdWLabel, qrMthd, encryLv, weightsExact, colTrunc)

    print("="*60)
    print("Problem3: Performance on small scale problem with column truncation")
    nSample = 1000
    nFeatures = [3, 3, 5, 11, 8]
    colTrunc = True
    print("The test data are generated randomly and consist of ", nSample, " samples and ", sum(nFeatures), " features")
    encryLv = 3
    XTrain, YTrain, XInfer = linreg_setup.generate_fullrank_test_data(nSample, 0, nFeatures, dataMax)
    weightsExact = solve_weights_numpy_least_square(XTrain, YTrain)
    solve_weights_qr(XTrain, YTrain, colTrunc)
    solve_weights_federated_qr(XTrain, YTrain, nFeatures, clientIdWLabel, qrMthd, encryLv, weightsExact, colTrunc)

    print("="*60)
    print("Problem4: Performance on large scale problem with column truncation")
    nSample = 1000000
    nFeatures = [40, 20, 30, 100, 10]
    colTrunc = True
    print("The test data are generated randomly and consist of ", nSample, " samples and ", sum(nFeatures), " features")
    encryLv = 3
    XTrain, YTrain, XInfer = linreg_setup.generate_fullrank_test_data(nSample, 0, nFeatures, dataMax)
    weightsExact = solve_weights_numpy_least_square(XTrain, YTrain)
    solve_weights_qr(XTrain, YTrain, colTrunc)
    solve_weights_federated_qr(XTrain, YTrain, nFeatures, clientIdWLabel, qrMthd, encryLv, weightsExact, colTrunc)

# Start the demo.
if __name__ == "__main__":
    demo_performance_qr(qrMthd="HouseHolder")
    demo_performance_qr(qrMthd="GramSchmidt")


"""
BASICS

Calculates the finite difference coefficients for a single variable
"""

from math import factorial
import numpy as np

# Number of coefficients needed
# m (int): Derivative
# n (int): Accuracy
def coefficient_number(m, n):
    return 2*((m+1)//2) -1 +n

# Finds the middle point of a list with a guaranteed odd number of elements
def oddcenter(L):
    return int(len(L)/2)

# Computes the actual coefficents
def finite_difference_coefficients(m, n, h):

    cn = coefficient_number(m, n)
    p = (cn - 1)//2

    m0 = np.zeros(cn)

    m0[m] = factorial(m)
    M = np.zeros((2*p+1, cn))

    for row in range(0, 2*p + 1):
        for col in range(0, 2*p+1):
            M[row][col] = (-p + col)**row

    return list((h**m)*np.linalg.solve(M, m0))

# Creates the u matrix for each derivative
# coefficients (arr) (float): Array of coefficients
# ts (int): Total size or resolution, so that the final matrix will be square and ts*ts dimensions
def partial_matrix(coefficients, ts):

    mc = oddcenter(coefficients)
    lc = len(coefficients)
    PM = np.zeros((ts, ts))
    center = coefficients[mc]

    for row in range(0, ts):

        PM[row][row] = center

        # Goes back and forth
        left_elements = min((lc-1)//2, row)
        right_elements = min((lc-1)//2, ts-row-1)

        for qq in range(1, left_elements+1):
            PM[row][row-qq] = coefficients[mc-qq]

        for hh in range(1, right_elements+1):
            PM[row][row+hh] = coefficients[mc+hh]

    return PM


import superimport

import numpy as np
import matplotlib.pyplot as plt
import os
import pyprobml_utils as pml

np.random.seed(0)
N = 5000
r = 2
xs = np.random.uniform(low=-r, high=r, size=N)
ys = np.random.uniform(low=-r, high=r, size=N)
rs = xs ** 2 + ys ** 2
inside = (rs <= r**2)
samples = 4*(r**2)*inside
Ihat = np.mean(samples)
pi_estimate = Ihat/(r**2)
se = np.sqrt(np.var(samples)/N)
print(('the estimated pi = %f' % pi_estimate))
print(('the standard pi = %f' % np.pi))
print(('stderr = %f' % se))

plt.figure(figsize=(5, 5))
plt.plot(xs[inside], ys[inside], 'bo')
plt.plot(xs[~inside], ys[~inside], 'rD')
pml.savefig('mcEstimatePi.pdf')
plt.show()


import numpy as np
import matplotlib.pyplot as plt

from scipy.spatial.distance import pdist, squareform
from scipy import exp
from scipy.linalg import eigh
from sklearn.datasets import make_moons

def rbf_kernel_pca(x, gamma, n_comps):
    """Radial-Basis Kernel PCA

    gamma - tuning param

    n_comps  - numbrer of principal components to return
    """

    # Calc pairwise squared Euclidian dists in mxn dimm dataset
    sq_dists = pdist(x, 'sqeuclidean')

    # Convert pairwise squared Eculidian dist into a square matrix
    mat_sq_dists = squareform(sq_dists)

    # Compute the symetric kernel matrix
    k = exp(-gamma * mat_sq_dists)

    # Center the kernel matrix
    n = k.shape[0]
    one_n = np.ones((n, n)) / n
    k = k - one_n.dot(k) - k.dot(one_n) + one_n.dot(k).dot(one_n)

    # Obtain eigenpairs from the centered kernel matrix
    eigvals, eigvecs = eigh(k)

    # Collect top k eigenvectors(proejcted samples)
    alphas = np.column_stack((eigvecs[:, -i] for i in range(1, n_comps+1)))

    # Collect corresp eigenvalues
    lambdas = [eigvals[-i] for i in range(1, n_comps+1)]

    return alphas, lambdas

def project_x(x_new, x, gamma, alphas, lamdas):
    pair_dist = np.array([np.sum((x_new - row)**2) for row in x])
    k = np.exp(-gamma * pair_dist)
    return k.dot(alphas/ lambdas)

x, y = make_moons(n_samples=100, random_state=123)

alphas, lambdas = rbf_kernel_pca(x, gamma=15, n_comps=1)

x_new = x[25]
print('x_new: ', x_new)

x_proj = alphas[25]  # original projection
print('x_proj: ', x_proj)

x_reproj = project_x(x_new, x, gamma=15, alphas=alphas, lamdas=lambdas)
print('x_reproj: ', x_reproj)

plt.scatter(alphas[y == 0, 0], np.zeros(50), color='red', marker='^', alpha=0.5)
plt.scatter(alphas[y == 1, 0], np.zeros(50), color='blue', marker='o', alpha=0.5)
plt.scatter(x_proj, 0, color='black', label='original projection of point x(25)')
plt.scatter(x_proj, 0, color='green', marker='x', s=500)
plt.legend(scatterpoints=1)
plt.show()


import numpy as np
import matplotlib.pyplot as plt

def sqrt_bisection(A):
    assert (A > 0)
    low = 0
    high = A
    mid = (low + high) * 0.5
    square = mid * mid
    t = 0
    time = [t]
    mids = [mid]
    lh = [float(high - low) * 0.5]
    errs = [float(A - square)]
    sqs = [square]
    while abs(square - A) > 2e-2:
        t += 1
        if square > A:
            high = mid
        else:
            low = mid
        mid = (low + high) * 0.5
        square = mid * mid
        time.append(t)
        mids.append(mid)
        lh.append(float(high - low) * 0.5)
        sqs.append(square)
        errs.append(float(A - square))

    fig, (ax0, ax1) = plt.subplots(nrows=2, sharex=True)
    ax0.errorbar(time, sqs, yerr=errs, linestyle='dotted', fmt='-o')
    ax0.set_yscale('log')
    ax0.set_xlabel('Step')
    ax0.set_ylabel('Sqrt')

    ax1.errorbar(time, mids, yerr=lh, linestyle='dotted', fmt='o')
    # ax1.set_yscale('log')
    ax1.set_ylabel('X')
    ax1.set_xlabel('Step')
    plt.show()

def sqrt_newton(A):
    assert (A > 0)
    xn = A * 0.5
    square = xn * xn
    t = 0
    time = [t]
    mids = [xn]
    errs = [float(A - square)]
    sqs = [square]
    while abs(square - A) > 1e-6:
        t += 1
        xn = (xn + A / xn) * 0.5
        square = xn * xn
        time.append(t)
        mids.append(xn)
        sqs.append(square)
        errs.append(float(A - square))

    errs = np.sqrt(np.abs(errs))

    fig, (ax0, ax1) = plt.subplots(nrows=2, sharex=True)
    ax0.errorbar(time, sqs, yerr=errs**2, linestyle='dotted', fmt='-o')
    ax0.set_yscale('log')
    ax0.set_xlabel('Step')
    ax0.set_ylabel('Sqrt')

    ax1.errorbar(time, mids, yerr=errs, linestyle='dotted', fmt='o')
    ax1.set_ylabel('X')
    ax1.set_xlabel('Step')
    plt.show()

if __name__ == "__main__":
    sqrt_bisection(1000)
    # sqrt_newton(1000)


import numpy as np
from scipy.spatial import distance
import argparse

parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument("--var",type=int,required=True,help="Constant (C)")
parser.add_argument("--dim_dense",type=int,required=True,help=" dimension of the final embedding/dense layer of the model")
parser.add_argument("--num_class",type=int,required=True,help="number of classes in the dataset")
parser.add_argument("--sim",type=int,required=True,help="similarity between the classes (0-1)")
parser.add_argument("--class1",type=int,required=True,help="index of the first class label that needs to be manipulated")
parser.add_argument("--class2",type=int,required=True,help="index of the second class label that needs to be manipulated")
parser.add_argument("--alpha1",type=int,required=True,help="percentage of weight from class1")
parser.add_argument("--alpha2",type=int,required=True,help="percentage of weight from class2")

args = parser.parse_args()

def generate_mmc_center(var, dim_dense, num_class):

    mmc_centers = np.zeros((num_class, dim_dense))
    mmc_centers[0][0] = 1
    for i in range(1,num_class):
        for j in range(i):
            mmc_centers[i][j] = - (1/(num_class-1) + np.dot(mmc_centers[i],mmc_centers[j])) / mmc_centers[j][j]
        mmc_centers[i][i] = np.sqrt(np.absolute(1 - np.linalg.norm(mmc_centers[i]))**2)
    for k in range(num_class):
        mmc_centers[k] = var * mmc_centers[k]

    return mmc_centers

def manipulate(mmc_center,l,u,alpha1,alpha2,similarity):

    score = 0.4*mmc_center[l-1][l-1] + 0.6*mmc_center[u-1][u-1]
    print(score)
    #print(np.linalg.norm(mmc_center[l-1])**2)
    mmc_center[l-1][l-1]= score - similarity
    #print(np.linalg.norm(mmc_center[l-1])**2)
    mmc_center[l-1][u-1]= np.sqrt(1 - np.linalg.norm(mmc_center[l-1])**2)

    mmc_center[u-1][u-1]= score - similarity
    mmc_center[u-1][l-1]=0
    #print(np.linalg.norm(mmc_center[u-1])**2)
    mmc_center[u-1][l-1]=np.sqrt(1 - np.linalg.norm(mmc_center[u-1])**2)

    return mmc_center

var, dim_dense, num_class = args.var, args.dim_dense, args.num_class
mmc_center = generate_mmc_center(var, dim_dense, num_class)

mmc_center_local=mmc_center.copy()

class1, class2, alpha1, alpha2, similarity = args.class1, args.class2, args.alpha1, args.alpha2, args.sim
final_centers= manipulate(mmc_center_local,class1,class2,alpha1,alpha2,similarity)

before_dist_matrix=distance.cdist(mmc_center,mmc_center , 'euclidean')
after_dist_matrix=distance.cdist(final_centers, final_centers, 'euclidean')

print("Intial distance:", before_dist_matrix)
print("Final distance:", after_dist_matrix)

#import scipy.io as sio
#sio.savemat('./new_params/meanvar'+str(C)+'_featuredim'+str(n_dense)+'_class'+str(class_num)+'.mat', {'mean_logits': mmc_center})


import tensorflow as tf
import numpy as np

#construct tensorflow graph: w*x=y
x_placeHolder1=tf.placeholder(tf.float32, [None])
x_placeHolder2 = tf.placeholder(tf.float32, [None])
weight1=tf.Variable([0.0]) #the weight we will adjust to fit our model
weight2 = tf.Variable([0.0])
bias = tf.Variable([1.0]) # added so we can compute datapoints for y = x + 1
y_fit=weight1*x_placeHolder1 + weight2*x_placeHolder2 #the y values estimated from our model

y_placeHolder=tf.placeholder(tf.float32, [None]) #the correct y values
loss=tf.reduce_mean(tf.square(tf.subtract(y_fit, y_placeHolder))) #aka mean squared error

#specify the optimization function
global_step=tf.Variable(0, name='global_step', trainable=False)
optimizer=tf.train.GradientDescentOptimizer(0.1) #gradient descent optimizer with steps scaled by 0.1
train_op=optimizer.minimize(loss, global_step=global_step) #optimization function

session=tf.Session() #compile graph
session.run(tf.initialize_all_variables())

#data points from function we want to fit
X_data1=np.asarray([0.0, 1.0, 2.0, 3.0, 4.0])
X_data2=np.asarray([0.0, 1.0, 2.0, 3.0, 4.0])
Y_data=np.asarray([0.0, 4.0, 8.0, 12.0, 16.0])

#fit our model
for step in range(1000):
    session_loss, _=session.run(
        [loss, train_op], #graph variable we want to compute
        feed_dict={x_placeHolder1: X_data1, x_placeHolder2: X_data2, y_placeHolder: Y_data}) #inputs to the graph we must specify so we can compute above vars
    print('loss', session_loss)

    fitted_ys=session.run(
        y_fit, #graph variable we want to compute
        feed_dict={x_placeHolder1: X_data1, x_placeHolder2: X_data2}) #inputs to the graph we must specify so we can compute above vars
    print('fitted y\'s', fitted_ys)

# weight=1.0
# def fit_points_with_model(x_placeHolder):
#     global weight
#     y_fit=weight*x_placeHolder
#     return y_fit

# fitted_ys=fit_points_with_model(X_data)
# print('fitted y\'s', fitted_ys)


# -*- coding: utf-8 -*-
"""
Created on Wed Oct 27 15:43:40 2021

@author: Bing

Computing multidimensional Gaussian integral with Gaussian-Hermite quadrature
"""

from scipy.special import roots_hermite
import numpy as np
from math import sqrt, pi
import itertools

class Quadrature():
    def __init__(self):

        self.x = None
        self.w = None

    def gauss_hermite(self, n, mu=None, sigma=None):
        """
        Compute int f(x) exp(-x^2) dx = sum_{i=0}^n w[i] * f(x[i])
        using Gaussian-Hermite quadrature

        Parameters
        ----------
        n : TYPE
            DESCRIPTION.
        mu : TYPE, optional
            DESCRIPTION. The default is None.
        sigma : TYPE, optional
            DESCRIPTION. The default is None.

        Returns
        -------
        TYPE
            DESCRIPTION.
        w : TYPE
            DESCRIPTION.

        """
        return gauss_hermite_quadrature(n, mu=mu, sigma=sigma)

    def integrate(self, f):

        x = self.x
        w = self.w

        const = 1./sqrt(pi)

        return np.sum(w * const * f(x))

def gauss_hermite_quadrature(n, mu=None, sigma=None):
    """
    Compute int f(x) exp(-x^2) dx = sum_{i=0}^n w[i] * f(x[i])
    using Gaussian-Hermite quadrature

    Parameters
    ----------
    n : TYPE
        DESCRIPTION.
    mu : TYPE, optional
        DESCRIPTION. The default is None.
    sigma : TYPE, optional
        DESCRIPTION. The default is None.

    Returns
    -------
    TYPE
        DESCRIPTION.
    w : TYPE
        DESCRIPTION.

    """
    x, w = roots_hermite(n)
    if mu is not None:
        y = sqrt(2.) * sigma * x + mu

        return y, w
    else:
        return x, w

# x, w = roots_hermite(10)
const = 1./sqrt(pi)

x, w = gauss_hermite_quadrature(20, mu=0, sigma=1)
def f(x):
    return np.sin(x)

ps = np.linspace(-5,5)
# for p in ps:
g = [np.sum( w * const * np.exp(-1j * p * x)) for p in ps]

import proplot as plt
fig, ax = plt.subplots()

ax.plot(ps, np.real(g))

# multidimensional
mu = np.array([1, 0])
Sigma = np.array([[1.3, -0.213], [-0.213, 1.2]])
N = len(mu)
const = np.pi**(-0.5*N)
xn = np.array(list(itertools.product(*(x,)*N)))

print(xn.shape)

wn = np.prod(np.array(list(itertools.product(*(w,)*N))), 1)
yn = 2.0**0.5*np.dot(np.linalg.cholesky(Sigma), xn.T).T + mu[None, :]
print("Normalising constant: %f" % np.sum(wn * const))
print("Mean:")
print(np.sum((wn * const)[:, None] * yn, 0))
print("Covariance:")
covfunc = lambda x: np.outer(x - mu, x - mu)
print(np.sum((wn * const)[:, None, None] * np.array(list(map(covfunc, yn))), 0))


import math
from sympy import Range

def is_prime(number: int) -> bool:
    for i in Range(2, math.sqrt(number)):
        if number % i == 0:
            return False
    return True

def generate_twins(start: int, end: int) -> None:
    for i in Range(start, end):
        j = i + 2
        if (is_prime(i) and is_prime(j)):
            print("{:d} and {:d}".format(i, j))

if __name__ == '__main__':
    lower_limit: int = int(input("Enter the lower limit: "))
    higher_limit: int = int(input("Enter the higher limit: "))
    generate_twins(lower_limit, higher_limit)


#coding: utf8
import matplotlib.pyplot as plt
import math
import numpy as np

xList = range(100)

y1 = [x*x for x in xList]
y2 = [math.sin(x) for x in xList]
y3 = [math.sqrt(x) for x in xList]

def draw():
    # plt.plot(y1, 'b-',  label='y=x*x')
    plt.plot(y2, label='y=sin(x)')
    plt.plot(y3, 'r*', label='y=sqrt(x)')
    plt.grid()
    plt.legend()
    plt.show()

def drawWithTicks():
    # plt.plot(y1, 'b-',  label='y=x*x')
    plt.plot(y2, label='y=sin(x)')
    plt.plot(y3, 'r*', label='y=sqrt(x)')
    yticks = np.arange(min(y2), max(y2), 1) # 设置坐标轴刻度
    plt.yticks(yticks)
    plt.ticklabel_format(style='sci', axis='x', scilimits=(0,0)) # 坐标轴用科学计数法
    plt.grid()
    plt.legend()
    plt.show()

draw()

xList = range(1, 23)

y = [math.sqrt((x**3 + 7*x + 11) % 23) for x in xList]
y2 = [-math.sqrt((x**3 + 7*x + 11) % 23) for x in xList]
def drawElliptic():
    plt.plot(xList, y)
    plt.plot(xList, y2)
    plt.grid()
    plt.show()

drawElliptic()