import numpy as np

def QRDecomposition(A):
	n = np.shape(A)[0] #pegando o tamanho das linhas de A
	m = np.shape(A)[1] #pegando o tamanho das colunas de A
	Q = np.zeros((n,m)) #declarando a matriz Q
	R = np.zeros((m,m)) #declarando a matriz R

	for j in range(0, m):
		A_column = A[:, j] #pegando as colunas da matriz A
		V = np.zeros(n) #declarando o vetor V
		V = A_column #V igual a coluna j de A
		for i in range (0, j):
			R[i,j] = Q[:,i].dot(A_column) #fazendo o calculo do R[i,j] = coluna i de Q * coluna j de A ( i != j)
			V -= (Q[:,i].dot(A_column))*Q[:,i] #fazendo o calculo de V
		R[j,j] = np.linalg.norm(V) # R[j,j] = norma da coluna j de A (i == j)
		Q[:,j] = V/np.linalg.norm(V) #normalizando V e atribuindo a coluna j de Q

	return Q, R

def decompLU(A):
	L = np.eye(np.shape(A)[0]) #matriz L com a dimensao de A com a diagonal principla igual a 1
	U = np.zeros(np.shape(A)) #matriz U full zero
	lim = np.shape(A)[1] #pegando o tamanho da coluna de A (matriz quadrada)
	sum = 0

	for i in range(0, lim):
		for j in range(0, lim):
			sum = 0
			#Parte do somatorio de U que vai de 0 a i-1 e acumula L[i][k]*U[k][j] sendo k a variavel iteradora
			for k in range (0, i):
				sum += L[i,k]*U[k,j]
			U[i,j] = A[i,j] - sum #atribuindo o valor de U[i][j]

		for j in range (0, lim):
			sum = 0
			#Parte do somatorio de L que vai de 0 a i-1 e acumula L[j][k]*U[k][i] sendo k a variavel iteradora
			for k in range (0, i):
				sum+= L[j,k]*U[k,i]
			L[j,i] = (A[j,i] - sum)/U[i,i] #atribuindo o valor L[i][j]

	return L, U #retornando o resultado

def solveLU(L, U, b):
	#Resolvendo o sistema A*x = b
	#Como A = L*U, entao (L*U)*x = b
	#Vamos fazer L*(U*x) = b e U*x=y, portanto L*y=b
	#Logo, para encontrarmos o resultado resolvemos o sistema U*x = y

	y = np.zeros(np.shape(b)) #matriz coluna y com a mesma dimensao de b
	x = np.zeros(np.shape(b)) #matriz coluna x (resultado do sistema) com a mesma dimensao de b

	for i in range (0, np.shape(b)[0]): #resolvendo o sistema  L*y=b
		for j in range (0,i):
			y[i] -= y[j]*L[i,j]
		y[i]+=b[i]

	for i in range (np.shape(b)[0]-1, -1, -1): #resolvendo o sistema U*x=b
		for j in range (np.shape(b)[0]-1, i, -1):
			x[i] -= x[j]*U[i,j]
		x[i]+=y[i]
		x[i]/=U[i,i]

	return x #retornando o resultado

def LeastSquaresQR(x, y, n):
	#Realizar a resolucao do sistema R*alpha = (Q^T)*y
	V = np.vander(x,n) #criando a matriz de vandermonde V
	(Q,R) = QRDecomposition(V) #fazendo a decomposicao V = Q*R
	b = np.transpose(Q).dot(y) #criando a matriz b = (Q^T)*y
	(L,U) = decompLU(R) #fazendo a decomposicao LU de R
	alpha = solveLU(L,U,b) #resolvendo o sistema usando a decomposicao LU (R*alpha = b / L*U*alpha = b)
	return alpha[::-1] #retornando o vetor ao contrario

x = [-1.0, 0.0, 1.0, 2.0];
y = [0.0, -1.0, 0.0, 7.0];
print(x)
print(y)

alpha = LeastSquaresQR(x, y, 2+1) #como queremos uma aproximacao para um polinomio do segundo grau o n = 2+1

print(alpha)


'''
Compute graph transitivity, the fraction of all possible triangles present in G.

'''

import networkx as nx

def calculate(network):
    try:
        n = nx.transitivity(network)
    except:
        n = 0
    return round(n, 5)


# -----------------------------------------------------------------------------
# From https://en.wikipedia.org/wiki/Minkowski–Bouligand_dimension:
#
# In fractal geometry, the Minkowski–Bouligand dimension, also known as
# Minkowski dimension or box-counting dimension, is a way of determining the
# fractal dimension of a set S in a Euclidean space Rn, or more generally in a
# metric space (X, d).
# -----------------------------------------------------------------------------

# From https://github.com/rougier/numpy-100 (#87)
# From https://gist.github.com/rougier/e5eafc276a4e54f516ed5559df4242c0

import numpy as np

def boxcount(Z, k):
    """
    returns a count of squares of size kxk in which there are both colours (black and white), ie. the sum of numbers
    in those squares is not 0 or k^2
    Z: np.array, matrix to be checked, needs to be 2D
    k: int, size of a square
    """
    S = np.add.reduceat(
        np.add.reduceat(Z, np.arange(0, Z.shape[0], k), axis=0),
        np.arange(0, Z.shape[1], k), axis=1)  # jumps by powers of 2 squares

    # We count non-empty (0) and non-full boxes (k*k)
    return len(np.where((S > 0) & (S < k * k))[0])

def boxcount_grayscale(Z, k):
    """
    find min and max intensity in the box and return their difference
    Z - np.array, array to find difference in intensities in
    k - int, size of a box
    """
    S_min = np.fmin.reduceat(
        np.fmin.reduceat(Z, np.arange(0, Z.shape[0], k), axis=0),
        np.arange(0, Z.shape[1], k), axis=1)
    S_max = np.fmax.reduceat(
        np.fmax.reduceat(Z, np.arange(0, Z.shape[0], k), axis=0),
        np.arange(0, Z.shape[1], k), axis=1)
    return S_max - S_min

def fractal_dimension(Z, threshold=0.9):
    """
    calculate fractal dimension of an object in an array defined to be above certain threshold as a count of squares
    with both black and white pixels for a sequence of square sizes. The dimension is the a coefficient to a poly fit
    to log(count) vs log(size) as defined in the sources.
    :param Z: np.array, must be 2D
    :param threshold: float, a thr to distinguish background from foreground and pick up the shape, originally from
    (0, 1) for a scaled arr but can be any number, generates boolean array
    :return: coefficients to the poly fit, fractal dimension of a shape in the given arr
    """
    # Only for 2d image
    assert (len(Z.shape) == 2)

    # Transform Z into a binary array
    Z = (Z < threshold)

    # Minimal dimension of image
    p = min(Z.shape)

    # Greatest power of 2 less than or equal to p
    n = 2 ** np.floor(np.log(p) / np.log(2))

    # Extract the exponent
    n = int(np.log(n) / np.log(2))

    # Build successive box sizes (from 2**n down to 2**1)
    sizes = 2 ** np.arange(n, 1, -1)

    # Actual box counting with decreasing size
    counts = []
    for size in sizes:
        counts.append(boxcount(Z, size))

    # Fit the successive log(sizes) with log (counts)
    coeffs = np.polyfit(np.log(sizes), np.log(counts), 1)
    return -coeffs[0]

def fractal_dimension_grayscale(Z):
    """
    works the same as fractal_dimension() just does not look at counts and does not require a binary arr rather is looks
    at intensities (hence can be used for a grayscale image) and returns fractal dimensions D_B and D_M (based on sums
    and means), as described in https://imagej.nih.gov/ij/plugins/fraclac/FLHelp/Glossary.htm#grayscale
    :param Z: np. array, must be 2D
    :return: D_B and D_M fractal dimensions based on polyfit to log(sum) or log(mean) resp. vs log(sizes)
    """
    # Only for 2d image
    assert (len(Z.shape) == 2)

    # Minimal dimension of image
    p = min(Z.shape)

    # Greatest power of 2 less than or equal to p
    n = 2 ** np.floor(np.log(p) / np.log(2))

    # Extract the exponent
    n = int(np.log(n) / np.log(2))

    # Build successive box sizes (from 2**n down to 2**1)
    sizes = 2 ** np.arange(n, 1, -1)

    # Actual box counting with decreasing size
    i_difference = []
    for size in sizes:
        i_difference.append(boxcount_grayscale(Z, size))

    # D_B
    d_b = [np.sum(x) for x in i_difference]

    # D_M
    d_m = [np.mean(x) for x in i_difference]

    # Fit the successive log(sizes) with log (sum)
    coeffs_db = np.polyfit(np.log(sizes), np.log(d_b), 1)
    # Fit the successive log(sizes) with log (mean)
    coeffs_dm = np.polyfit(np.log(sizes), np.log(d_m), 1)

    return -coeffs_db[0], -coeffs_dm[0]

def fractal_dimension_grayscale_DBC(Z):
    """
    Differential box counting method with implementation of appropriate box height selection.
    :param Z: 2D np.array
    :return: fd for a grayscale image
    """
    # Only for 2d image
    assert (len(Z.shape) == 2)

    # Minimal dimension of image
    p = min(Z.shape)

    # Greatest power of 2 less than or equal to p
    n = 2 ** np.floor(np.log(p) / np.log(2))

    # Extract the exponent
    n = int(np.log(n) / np.log(2))

    # Build successive box sizes (from 2**n down to 2**1)
    sizes = 2 ** np.arange(n, 1, -1)

    # get the mean and standard deviation of the image intensity to rescale r
    mu = np.mean(Z)
    sigma = np.std(Z)

    # total number of gray levels, used for computing s'
    G = len(np.unique(Z))

    # scaled scale of each block, r=size(s)
    # TODO -- when to rescale, what should a be
    # when to rescale -- either always or when the pixels in the selected box don't fall in +- 1 std, so far always
    a = 1
    r_prime = sizes / (1 + 2 * a * sigma)

    # Actual box counting with decreasing size
    i_difference = []
    for size in sizes:
        # rescale
        n_r = np.ceil(boxcount_grayscale(Z, size) / r_prime)
        # if max==min per the box, replace the 0 result with 1
        n_r[n_r == 0] = 1
        i_difference.append(n_r)

    # contribution from all boxes
    N_r = [np.sum(x) for x in i_difference]

    # Fit the successive log(sizes) with log (sum)
    coeffs = np.polyfit(np.log(sizes), np.log(N_r), 1)

    return -coeffs[0]


#!/usr/bin/python
#-*- encoding: utf-8 -*-
"""
Copyright (c) 2015 @myuuuuun
Released under the MIT license.
"""

import math
import numpy as np
import functools
import matplotlib.pyplot as plt
import matplotlib.cm as cm
EPSIRON = 1.0e-8

# P0〜P_(length-1)までのルジャンドル多項式の, xにおける値の配列を返す
def legendre(x, length):
    values = [1, x]
    for i in range(2, length):
        v = ((2*i-1)*x*values[i-1] - (i-1) * values[i-2]) / i
        values.append(v)

    return values

# P0〜P_(length-1)までのチェビシェフ多項式の, xにおける値の配列を返す
def chebyshev(x, length):
    values = []
    for i in range(length):
        v = np.cos(i * np.arccos(x))
        values.append(v)

    return values

if __name__ == '__main__':
    # 共通設定
    length = 6
    x_list = np.arange(-0.99, 1.00, 0.01)
    f_matrix = np.zeros((length, 199), dtype=float)

    # legendre
    """
    for i, x in enumerate(x_list):
        values = legendre(x, length)
        for j in range(length):
            f_matrix[j][i] = values[j]

    fig, ax = plt.subplots()
    plt.title("Legendre多項式")

    plt.xlabel("x")
    plt.ylabel("f")
    plt.xlim(-1, 1)
    for j in range(length):
        plt.plot(x_list, f_matrix[j], color=cm.gist_earth(j/length), label='P{0}'.format(j))
    plt.legend()
    plt.show()
    """

    """
    # chebyshev
    for i, x in enumerate(x_list):
        values = chebyshev(x, length)
        for j in range(length):
            f_matrix[j][i] = values[j]

    fig, ax = plt.subplots()
    plt.title("Chebyshev多項式")

    plt.xlabel("x")
    plt.ylabel("f")
    plt.xlim(-1, 1)
    for j in range(length):
        plt.plot(x_list, f_matrix[j], color=cm.gist_earth(j/length), label='P{0}'.format(j))
    plt.legend()
    plt.show()
    """


from pprint import pprint
from numpy import array, zeros, diag, diagflat, dot

def jacobi(A,b,N=25,x=None):
    """Solves the equation Ax=b via the Jacobi iterative method."""
    # Create an initial guess if needed
    if x is None:
        x = zeros(len(A[0]))

    # Create a vector of the diagonal elements of A
    # and subtract them from A
    D = diag(A)
    R = A - diagflat(D)

    # Iterate for N times
    for i in range(N):
        x = (b - dot(R,x)) / D
    return x

A = array([[2.0,1.0],[5.0,7.0]])
b = array([11.0,13.0])
guess = array([1.0,1.0])

sol = jacobi(A,b,N=25,x=guess)

print("A:")
pprint(A)

print("b:")
pprint(b)

print("x:")
pprint(sol)


from sklearn import (datasets,random_projection)
from time import time
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import offsetbox
from isomap import isomap
from mpl_toolkits.mplot3d import Axes3D

digits = datasets.load_digits(n_class=6)
X = digits.data
y = digits.target
n_samples, n_features = X.shape
n_neighbors = 30
X_tmp = X[:10,:]
#----------------------------------------------------------------------
# Scale and visualize the embedding vectors
def plot_embedding(X, title=None):
    x_min, x_max = np.min(X, 0), np.max(X, 0)
    X = (X - x_min) / (x_max - x_min)

    plt.figure()
    ax = plt.subplot(111)
    for i in range(X.shape[0]):
        plt.text(X[i, 0], X[i, 1], str(digits.target[i]),
                 color=plt.cm.Set1(y[i] / 10.),
                 fontdict={'weight': 'bold', 'size': 9})

    if hasattr(offsetbox, 'AnnotationBbox'):
        # only print thumbnails with matplotlib > 1.0
        shown_images = np.array([[1., 1.]])  # just something big
        for i in range(digits.data.shape[0]):
            dist = np.sum((X[i] - shown_images) ** 2, 1)
            if np.min(dist) < 4e-3:
                # don't show points that are too close
                continue
            shown_images = np.r_[shown_images, [X[i]]]
            imagebox = offsetbox.AnnotationBbox(
                offsetbox.OffsetImage(digits.images[i], cmap=plt.cm.gray_r),
                X[i])
            ax.add_artist(imagebox)
    plt.xticks([]), plt.yticks([])
    if title is not None:
        plt.title(title)

    # Plot images of the digits
n_img_per_row = 30
img = np.zeros((10 * n_img_per_row, 10 * n_img_per_row))
for i in range(n_img_per_row):
    ix = 10 * i + 1
    for j in range(n_img_per_row):
        iy = 10 * j + 1
        img[ix:ix + 8, iy:iy + 8] = X[i * n_img_per_row + j].reshape((8, 8))

plt.imshow(img, cmap=plt.cm.binary)
plt.xticks([])
plt.yticks([])
plt.title('A selection from the 64-dimensional digits dataset')

# Random 2D projection using a random unitary matrix
print("Computing random projection")
rp = random_projection.SparseRandomProjection(n_components=2, random_state=42)
X_projected = rp.fit_transform(X)
plot_embedding(X_projected, "Random Projection of the digits")

# Isomap projection of the digits dataset
print("Computing Isomap embedding")
t0 = time()
embedding = isomap(input=X, n_neighbors=n_neighbors, n_components=2, n_jobs=4)
print("Done.")
plot_embedding(embedding,"Isomap projection of the digits (time %.2fs)" %(time() - t0))

embedding_three_dim = isomap(input=X, n_neighbors=n_neighbors, n_components=3, n_jobs=4)
# draw 32 plots
fig = plt.figure()
ax = Axes3D(fig)
ax.scatter(embedding_three_dim[:, 0], embedding_three_dim[:, 1], embedding_three_dim[:, 2], c=y)

01 Dimensionality Reduction/Tutorial 03 - Unsupervised nonlinear embedding/isomap/visualization.py


#!/usr/bin/env python
# -*- coding: utf-8 -*-
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from datetime import datetime, date

sample_size = 500
sigma_e = 3.0             # true value of parameter error sigma
random_num_generator = np.random.RandomState(0)
x = 10.0 * random_num_generator.rand(sample_size)
e = random_num_generator.normal(0, sigma_e, sample_size)
y = 1.0 + 2.0 * x +  e          # a = 1.0; b = 2.0; y = a + b*x

import tensorflow as tf

tf.reset_default_graph()            # reset graph
x_plus_i = np.c_[np.ones((500,1)), x]
X = tf.constant(x_plus_i, dtype=tf.float64, name='X')
# keep y as our original dataset; make a copy instead
y_copy = tf.constant(y.reshape(-1,1), dtype=tf.float64, name='y')
X_T = tf.transpose(X)
# Normal equation
beta = tf.matmul(tf.matmul(tf.matrix_inverse(tf.matmul(X_T, X)), X_T), y_copy)

with tf.Session() as sess:
    beta_value = sess.run(beta)
    print('pamameters: %.7f, %.7f' % (beta_value[0], beta_value[1]))

import tensorflow as tf

tf.reset_default_graph()
batch_size = 50
n_batches = int(500/batch_size)
n_epochs = 1000
learing_rate = 0.01

# define the graph
w = tf.Variable(tf.truncated_normal([1], mean=0.0, stddev=1.0, dtype=tf.float64, name='slope'))
b = tf.Variable(tf.zeros(1, dtype=tf.float64), name='intercept')
x_ph = tf.placeholder(tf.float64, shape=(None, 1), name='x')
y_ph = tf.placeholder(tf.float64, shape=(None, 1), name='y')
y_pred = tf.add(b, tf.multiply(w, x_ph), name='prediction')
error = y_pred - y_ph
mse = tf.reduce_mean(tf.square(error), name='mse')
optimizer = tf.train.GradientDescentOptimizer(learning_rate=learing_rate)
training_op = optimizer.minimize(mse)

# record to TensorBoard
from datetime import datetime
now = datetime.now().strftime('%Y%m%d%H%M%S')
logdir = 'tf_logs/run-{}'.format(now)
mse_summary = tf.summary.scalar('MSE', mse)
file_writer = tf.summary.FileWriter(logdir, tf.get_default_graph())

init = tf.global_variables_initializer()
with tf.Session() as sess:
    sess.run(init)

    for epoch in range(n_epochs):
        for batch_index in range(n_batches):
            # Mini-batch gradient descent
            x_batch = x[batch_index*batch_size:(batch_index+1)*batch_size].reshape(-1,1)
            y_batch = y[batch_index * batch_size:(batch_index + 1) * batch_size].reshape(-1, 1)
            sess.run(training_op, feed_dict={x_ph: x_batch, y_ph: y_batch})

            summary_str = mse_summary.eval(feed_dict={x_ph: x_batch, y_ph: y_batch})
            step = epoch *  n_batches + batch_index
            file_writer.add_summary(summary_str, step)

        w_val, b_val = sess.run([w, b])
        print('epoch {}: slope {}, intercept {}'.format(epoch, w_val[0], b_val[0]))

file_writer.close()


import scipy.stats
from math import fabs, sqrt, log, erf
import numpy as np
# from ..exts.statistics import NormalDist

def z_test(y1, y2, n1, n2):
    # two-tailed
    p1 = y1.mean()
    p2 = y2.mean()
    n1 = n1.mean().round()
    n2 = n2.mean().round()
    se = np.sqrt(p1*(1-p1)/n1 + p2*(1-p2)/n2)
    z = (p1 - p2) / se
    return z, scipy.stats.norm.sf(abs(z))*2

def calc_prob_overlapping(means, variances):
    sigma1, sigma2 = np.sqrt(variances)
    mu1, mu2 = means
    ### the bug causing entry had sigma1 == sigma2 and mu1 == mu2
    #print("sigma1: ",sigma1,"sigma2: ",sigma2)
    #print("mu1: ",mu1,"mu2: ",mu2)
    if sigma1 != sigma2 and mu1 != mu2:
        return NormalDist(mu=mu1, sigma=sigma1).overlap(NormalDist(mu=mu2, sigma=sigma2))
    else:
        return np.nan,[np.nan,np.nan,np.nan,np.nan]

class NormalDist(object):
    "Modified from the library statistics.py (Authors)(https://github.com/python/cpython/blob/3.8/Lib/statistics.py) which is under GPL-compatible license."
    def __init__(self, mu=0.0, sigma=1.0):
        self._mu = mu
        self._sigma = sigma

    def cdf(self, x):
        return 0.5 * (1.0 + erf((x - self._mu) / (self._sigma * sqrt(2.0))))

    def overlap(self, another):
        """
        Compute the overlapping coefficient (OVL) between two normal distributions.
        Measures the agreement between two normal probability distributions.
        Returns a value between 0.0 and 1.0 giving the overlapping area in
        the two underlying probability density functions.
        """
        # See: "The overlapping coefficient as a measure of agreement between
        # probability distributions and point estimation of the overlap of two
        # normal densities" -- Henry F. Inman and Edwin L. Bradley Jr
        # http://dx.doi.org/10.1080/03610928908830127
        X, Y = self, another
        if (Y._sigma, Y._mu) < (X._sigma, X._mu):  # sort to assure commutativity
            X, Y = Y, X
        X_var, Y_var = X.variance, Y.variance

        dv = Y_var - X_var
        dm = fabs(Y._mu - X._mu)
        if not dv:
            return 1.0 - erf(dm / (2.0 * X._sigma * sqrt(2.0)))
        a = X._mu * Y_var - Y._mu * X_var
        b = X._sigma * Y._sigma * sqrt(dm**2.0 + dv * log(Y_var / X_var))
        x1 = (a + b) / dv # intersection point 1
        x2 = (a - b) / dv # intersection point 2

        p_overlap = 1.0 - (fabs(Y.cdf(x1) - X.cdf(x1)) + fabs(Y.cdf(x2) - X.cdf(x2)))
        list_cdf_at_intersections = [X.cdf(x1),Y.cdf(x1),X.cdf(x2),Y.cdf(x2)]

        return p_overlap,list_cdf_at_intersections

    @property
    def mean(self):
        "Arithmetic mean of the normal distribution."
        return self._mu

    @property
    def stdev(self):
        "Standard deviation of the normal distribution."
        return self._sigma

    @property
    def variance(self):
        "Square of the standard deviation."
        return self._sigma ** 2.0


""" Provides core functions for converting between coordinate systems

Coord module provides simple module for converting between different coordinate
systems using numpy.
"""

import numpy as np

def cartesian2spherical(coords):
    """Convert Cartesian to Spherical coordinates.

    Converts an array of 3D Cartesian coordinates [x, y, z] to
    the equivalent array of Spherical coordinates [r, theta, phi].

    Parameters
    ----------
    coords: numpy.ndarray
            An m by 3 array of m Cartesian coordinates (x, y, z) in an
            3-dimensional space.

    Returns
    -------
    out_coords: numpy.ndarray
                Returns an m by 3 array of m Spherical coordinates in the
                order r (radial distance), theta (azimuth angle, radians)
                and phi (zenith angle, radians).
    """
    sphere = np.zeros(coords.shape)
    xy_sq = coords[:, 0]**2 + coords[:, 1]**2
    sphere[:, 0] = np.sqrt(xy_sq + coords[:, 2]**2)
    sphere[:, 1] = np.arctan2(coords[:, 1], coords[:, 0])
    sphere[:, 2] = np.arctan2(np.sqrt(xy_sq), coords[:, 2])
    return sphere

def spherical2cartesian(sphere):
    """Convert Spherical to Cartesian coordinates.

    Converts an array of Spherical coordinates [r, theta, phi] to
    the equivalent array of Cartesian coordinates [x, y, z].

    Parameters
    ----------
    coords: numpy.ndarray
            An m by 3 array of m Spherical coordinates in the
            order r (radial distance), theta (azimuth angle, radians)
            and theta (zenith angle, radians).

    Returns
    -------
    out_coords: numpy.ndarray
                Returns an m by 3 array of m Cartesian coordinates (x, y, z) in an
                3-dimensional space.
    """
    cart = np.zeros(sphere.shape, dtype=np.float64)
    sine_phi = np.sin(sphere[:, 2])

    cart[:, 0] = sphere[:, 0] * np.cos(sphere[:, 1]) * sine_phi
    cart[:, 1] = sphere[:, 0] * np.sin(sphere[:, 1]) * sine_phi
    cart[:, 2] = sphere[:, 0] * np.cos(sphere[:, 2])
    return cart

def spherical2cylindrical(sph):
    """Convert Spherical to Cylindrical coordinates.

    Converts an array of Spherical coordinates [r, theta, phi] to
    the equivalent array of Cylindrical coordinates [r, theta, z].

    Parameters
    ----------
    coords: numpy.ndarray
            An m by 3 array of m Spherical coordinates in the
            order r (radial distance), theta (azimuth angle, radians)
            and phi (zenith angle, radians).

    Returns
    -------
    out_coords: numpy.ndarray
                Returns an m by 3 array of m Cylindrical coordinates in the
                order r (radial distance), theta (azimuth angle, radians)
                and z (height).
    """
    cyl = np.zeros(sph.shape)
    cyl[:, 0] = sph[:, 0] * np.sin(sph[:, 2])
    cyl[:, 1] = sph[:, 1]
    cyl[:, 2] = sph[:, 0] * np.cos(sph[:, 2])
    return cyl

def cylindrical2spherical(cyl):
    """Convert Cylindrical to Spherical coordinates.

    Converts an array of Cylindrical coordinates [r, theta, z] to
    the equivalent array of Spherical coordinates [r, theta, phi].

    Parameters
    ----------
    coords: numpy.ndarray
            An m by 3 array of m Cylindrical coordinates in the
            order r (radial distance), theta (azimuth angle, radians)
            and z (height).

    Returns
    -------
    out_coords: numpy.ndarray
                Returns an m by 3 array of m Spherical coordinates in the
                order r (radial distance), theta (azimuth angle, radians)
                and phi (zenith angle, radians).
    """
    sph = np.zeros(cyl.shape)
    sph[:, 0] = np.sqrt(cyl[:, 0]**2 + cyl[:, 2]**2)
    sph[:, 1] = cyl[:, 1]
    sph[:, 2] = np.arctan2(cyl[:, 0], cyl[:, 2])
    return sph

def cartesian2cylindrical(coords):
    """Convert Cartesian to Cylindrical coordinates.

    Converts an array of 3D Cartesian coordinates [x, y, z] to
    the equivalent array of Cylindrical coordinates [r, theta, z].

    Parameters
    ----------
    coords: numpy.ndarray
            An m by 3 array of m Cartesian coordinates (x, y, z) in an
            3-dimensional space.

    Returns
    -------
    out_coords: numpy.ndarray
                Returns an m by 3 array of m Cylindrical coordinates in the
                order r (radial distance), theta (azimuth angle, radians)
                and z (height).
    """
    cyl = np.zeros(coords.shape)
    cyl[:, 0] = np.sqrt(coords[:, 0] ** 2 + coords[:, 1] ** 2)
    cyl[:, 1] = np.arctan2(coords[:, 1], coords[:, 0])
    cyl[:, 2] = coords[:, 2]
    return cyl

def cylindrical2cartesian(cylinder):
    """Convert Cylindrical to Cartesian coordinates.

    Converts an array of Cylindrical coordinates [r, theta, z] to
    the equivalent array of Cartesian coordinates [x, y, z].

    Parameters
    ----------
    coords: numpy.ndarray
            An m by 3 array of m Cylindrical coordinates in the
            order r (radial distance), theta (azimuth angle, radians)
            and z (height).

    Returns
    -------
    out_coords: numpy.ndarray
                Returns an m by 3 array of m Cartesian coordinates (x, y, z) in an
                3-dimensional space.
    """
    cart = np.zeros(cylinder.shape)
    cart[:, 0] = cylinder[:, 0] * np.cos(cylinder[:, 1])
    cart[:, 1] = cylinder[:, 0] * np.sin(cylinder[:, 1])
    cart[:, 2] = cylinder[:, 2]
    return cart


import numpy as np

# from numpy.linalg import det, inv

def main():

    """
    Basic matrix operations are supported by numpy.
    Addition, subtraction, multiplication, division by:
    - scalar
    - vector
    - matrix
    """

    matrix_A = np.array([[3, 9], [21, -3]])

    assert (matrix_A + 5 == np.array([[8, 14], [26, 2]])).all()
    assert (matrix_A - 1 == np.array([[2, 8], [20, -4]])).all()
    assert (matrix_A * 2 == np.array([[6, 18], [42, -6]])).all()
    assert (matrix_A / 3 == np.array([[1, 3], [7, -1]])).all()

    vector = [1, 2]
    assert (matrix_A + vector == np.array([[4, 11], [22, -1]])).all()
    assert (matrix_A - vector == np.array([[2, 7], [20, -5]])).all()
    assert (matrix_A * vector == np.array([[3, 18], [21, -6]])).all()
    assert (matrix_A / vector == np.array([[3, 4.5], [21, -1.5]])).all()

    matrix_B = np.array([[4, 9], [25, 16]])

    assert (np.sqrt(matrix_B) == np.array([[2, 3], [5, 4]])).all()

    assert (matrix_A + matrix_B == np.array([[7, 18], [46, 13]])).all()
    assert (matrix_A - matrix_B == np.array([[-1, 0], [-4, -19]])).all()
    assert (matrix_A * matrix_B == np.array([[12, 81], [525, -48]])).all()
    assert (matrix_B / matrix_A == np.array([[4 / 3, 1], [25 / 21, -16 / 3]])).all()

    """
    The transpose of a matrix is a reversal of its rows with its columns.
    Square matrices have determinants.
    The identity matrix is a square matrix with ones on the diagonal and zeros elsewhere.
    The inverse of a square matrix M is a matrix of the same size, N, such that M⋅N=I.
    """
    M = np.array([[-4, 5], [1, 7], [8, 3]])
    N = np.array([[3, -5, 2, 7], [-5, 1, -4, -3]])
    print(np.dot(M, N))

    assert (np.transpose(matrix_A) == np.array([[3, 21], [9, -3]])).all()
    assert (np.transpose(matrix_B) == np.array([[4, 25], [9, 16]])).all()

    assert np.linalg.det(matrix_A) == -198
    assert abs(np.linalg.det(matrix_B) + 161) < 0.001

    identity = np.eye(2)
    inverse = np.linalg.inv(matrix_A)
    product = np.dot(matrix_A, inverse)
    assert (product == identity).all()

if __name__ == "__main__":
    main()


import numpy as np

class LogisticRegression:
    '''
    将线性模型的结果用对数几率+阈值输出，转为离散变量，实现了回归到分类的连接。
    模型：sigmod函数：
    预测目标属于伯努利分布--伯努利分布同正态分布一样属于指数分布族--指数分布族的3个假设--推导出sigmod表达式
    详见：http://logos.name/archives/187
    策略：损失函数：
    由极大似然函数取对数再取反所得。
    首先要统一概率表达式：P(y|x,θ)=hθ(x)^y*(1−hθ(x))^(1−y)
    然后极大似然函数是P的连乘，损失函数是其对数取反。
    算法：梯度下降：
    利用g'(z) = g(z)(1-g(z))  z=w*x
    求导即得梯度为 X(hθ(X)−Y)
    故θ=θ−αX(hθ(X)−Y)
    '''
    def __init__(self,X,y,lr=0.01):
        self.X = np.c_[np.ones(len(X)),X]
        self.y = y
        self.theta = np.ones(self.X.shape[1])
        self.lr = lr
        self.sigmod = lambda X: 1/(1+np.e**(-X.dot(self.theta)))

    def loss(self):
        '''
        J(θ)=−lnL(θ)=−∑(y(i)log(hθ(x(i)))+(1−y(i))log(1−hθ(x(i))))其中i=[1,m]
        '''
        id1 = np.where(self.y==1)[0]
        id0 = np.where(self.y==0)[0]
        loss1 = -np.log(self.sigmod(self.X[id1])).sum()
        loss0 = -np.log(1-self.sigmod(self.X[id0])).sum()
        return loss1+loss0

    def train(self,max_iter = 400):
        '''BGD'''
        self.lossrst = []
        while len(self.lossrst)<=max_iter:
            errors = self.sigmod(self.X)-self.y
            self.theta -= self.lr*self.X.T.dot(errors)
            missed = ((self.X.dot(self.theta)>0)!=self.y).sum()
            self.lossrst.append((self.loss(), missed, self.theta))
        return 'train done!'

if __name__=='__main__':

    import pandas as pd
    df = pd.read_csv('./StatlogHeart.csv',header=None)
    y = df.pop(13).values-1
#    from sklearn.datasets import load_iris
#    iris = load_iris()
#    df = pd.DataFrame(iris.data, columns=iris.feature_names).iloc[:100,:2]
#    y = iris.target[:100]

    df = df.transform(lambda x:(x-x.mean())/x.std()) ## 标准化不可少

    LR = LogisticRegression(df.values,y,lr=0.0008)
    LR.train()
    train_info = pd.DataFrame(LR.lossrst,columns=['loss','missed','theta'])
    train_info.plot(y=['loss','missed'],secondary_y=['missed'],marker='o')


"""
Structure of a Neural Network to learn the `XOR` function
- 2 input features
- 2 hidden neurons
- 1 output neuron
"""
import numpy as np
import random
from time import time

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

if __name__ == '__main__':
    # Generate dataset of `XOR` examples
    # We define the array as suggested by Andrew Ng: features are rows, examples are columns
    # This makes the computation of the linear combination match the math closer: W^T * X
    x = np.array([[0., 0., 1., 1.], [0., 1., 0., 1.]])
    y = np.array([[0., 1., 1., 0.]])
    n = x.shape[1]

    seeds = [2, 10, 24, 45, 98, 120, 350, 600, 899, 1000]
    runtimes = []

    # Execute the training with each different seed and time them
    for seed in seeds:
        print(f"Running with seed: {seed}")
        random.seed(seed)
        start = time()

        # Initialize weights and biases
        # Remember: they have to be initialized to random values in order to break symmetry!
        # Input to hidden
        w0 = np.random.rand(2, 2)
        b0 = np.random.rand(2, 1)
        # Hidden to output
        w1 = np.random.rand(2, 1)
        b1 = np.random.rand(1, 1)

        # Train using gradient descent
        epochs = 100000
        alpha = 0.5

        for _ in range(epochs):
            # Forward propagation
            a1 = sigmoid(np.dot(w0.T, x) + b0)
            y_hat = sigmoid(np.dot(w1.T, a1) + b1)

            # Loss (MSE) multiplied by a 1/2 term to make the derivative easier
            _loss = (1. / (2. * n)) * np.sum((y_hat - y) ** 2)

            # Backpropagation
            dy_hat = (y_hat - y) / float(n)
            dz2 = (y_hat * (1. - y_hat)) * dy_hat
            dw1 = np.dot(a1, dz2.T)
            db1 = np.sum(dz2, axis=1, keepdims=True)
            dz1 = (a1 * (1. - a1)) * np.dot(w1, (dy_hat * (y_hat * (1. - y_hat))))
            dw0 = np.dot(x, dz1.T)
            db0 = np.sum(dz1, axis=1, keepdims=True)

            # Weight and bias update
            # We average the gradients so that we can use a larger learning rate
            w0 = w0 - alpha * (dw0 / float(n))
            w1 = w1 - alpha * (dw1 / float(n))
            b0 = b0 - alpha * (db0 / float(n))
            b1 = b1 - alpha * (db1 / float(n))

        # Record the time
        runtimes.append(round((time() - start) * 1000.))

    # Save runtimes to a file for further processing
    print('Saving runtimes to `python.txt`')
    with open('data/python.txt', 'w') as f:
        for t in runtimes:
            f.write(str(t) + '\n')


#! /usr/bin/env python3

import numpy as np
import scipy.fftpack
import numpy as np

class Signals:

    def __init__(self, Amplitude=0, Frequency=0, Phase=0, SamplesPerSecond=0, StopTime=0):
        self.Amplitude = Amplitude
        self.Frequency = Frequency
        self.Phase = Phase
        self.SamplesPerSecond = SamplesPerSecond
        self.StopTime = StopTime
        self.x = 0
        self.signal = 0
        self.fft = 0
        self.max_freq = 0
        return

    def SineWave(self):
        dt = 1/self.SamplesPerSecond
        self.x = np.arange(0, self.StopTime-dt, dt)
        self.signal = self.Amplitude * np.sin((2*np.pi*self.Frequency*self.x) + self.Phase)
        return self.signal

    def CosineWave(self):
        dt = 1/self.SamplesPerSecond
        self.x = np.arange(0, self.StopTime-dt, dt)
        self.signal = self.Amplitude * np.cos((2*np.pi*self.Frequency*self.x) + self.Phase)
        return self.signal

    def do_fft(self):
        self.fft = scipy.fftpack.fft(self.signal)
        return self.fft

    def max_frequency(self):
        """
        # https://stackoverflow.com/questions/3694918/how-to-extract-frequency-associated-with-fft-values-in-python
        """
        freqs = scipy.fftpack.fftfreq(len(self.fft))
        idx = np.argmax(np.abs(self.fft))
        freq = freqs[idx]
        self.max_freq = abs(freq * self.SamplesPerSecond)
        return self.max_freq

    def __add__(self, x):
        z = x.signal + self.signal
        signal =Signals()
        signal.signal = z
        return signal


'''
    Package: cs771
    Module: helloWorld
    Author: Puru
    Institution: CSE, IIT Kanpur
    License: GNU GPL v3.0

    Generate synthetic data of various sorts
'''

import numpy as np
import numpy.linalg as lin
import numpy.random as rnd

# Return n data points (as an n x d array) shaped as a hemisphere
# The manner of generation used below is similar to the sklearn
# method make_moons.However, the method below gives the additional
# flexibility of flipping and translating the moons
def genMoonData( d, n, mu, r, flipped = False ):
    X = np.vstack( (np.cos( np.linspace( 0, np.pi, n ) ), np.sin( np.linspace( 0, np.pi, n ) ) ) ).T
    if flipped:
	    X[:,1] = -np.abs( X[:,1] )
    else:
        X[:,1] = np.abs( X[:,1] )
    X = (X * r) + mu
    return X

# Return n data points (as an n x d array) sampled from N(mu, sigma^2 . I)
def genSphericalNormalData( d, n, mu, sigma ):
    X = rnd.normal( 0, sigma, (n, d) ) + mu
    return X

# Return n data points (as an n x d array) sampled from N(mu, cov)
def genNormalData( d, n, mu, cov ):
    X = rnd.multivariate_normal( mu, cov, n )
    return X

# Return n data points (as an n x d array) sampled from the surface of sphere of radius r centered at mu
def genSphericalData( d, n, mu, r ):
    X = rnd.normal( 0, 1, (n, d) )
    norms = lin.norm( X, axis = 1 )
    X = X / norms[:, np.newaxis]
    X = (X * r) + mu
    return X

# Return n data points (as an n x d array) sampled from the surface of ellipse of covariance cov centered at mu
def genEllipticalData( d, n, mu, cov ):
    X = genSphericalData( d, n, np.zeros((d,)), 1 )
    L = lin.cholesky( cov )
    X = np.matmul( X, L ) + mu
    return X


import numpy as np

data_path = "data/problem_07.txt"
# data_path = "data/problem_07_test.txt"

data = np.genfromtxt(data_path, dtype=int, delimiter=",")

# 🦀 🦀 🦀 🦀 🦀
# data = (np.random.random(162) * 100203).astype(np.int64) + 5

# part 1
print(f"Part 1 solution: {np.abs(data - int(np.median(data))).sum()}")

# part 2
# barbaric O(N * M) brute force way
# distances = np.abs(data.reshape(-1, 1) - np.arange(data.min(), data.max() + 1, dtype=np.int64))
# fuel_cost = (distances * (distances + 1) // 2).sum(axis=0)
# centroid = np.argmin(fuel_cost) + data.min()

# print(f"best position: {centroid}")
# print(f"Part 2 solution: {fuel_cost.min()}")

# elegant O(N) calculus way
# Unfortunately the cost function for 🦀_i is not continuously differentiable, so let's instead use
# the equation for the sum of an arithmetic series,
#
#      ε_i = s(s + 1)/2
#
# where
#        c = the centroid
#        s = (x_i - c) = the distance the 🦀 boi has to move
#
# find centroid c that minimizes the total cost ε:
#
#        ε = Σ[(x_i + c)(x_i - c + 1) / 2]
#
#    δε/δc = 1/2 δ/δc Σ[c² - (2x_i + 1)c]
#          = 1/2 Σ[2c - 2x_i - 1]
#          = 0
#      2cN = 2 Σ[x_i] - N
#        c = (2 Σ[x_i] - N) / 2N

centroid = int(np.round((2 * data.sum() - len(data)) / (2 * len(data))))

# Since our continuous cost function is not symmetrical about s = 0 and actually has a minumum at
# s = -1/2, the nearest integer centroid value is occasionally (when???) too low by 1.
# Let's just check the next integer up as well.
centroid_candidates = np.array([centroid, centroid + 1])
distances = np.abs(data.reshape(-1, 1) - centroid_candidates)
fuel_cost = (distances * (distances + 1) // 2).sum(axis=0)
centroid = centroid_candidates[np.argmin(fuel_cost)]

print(f"best position: {centroid}")
print(f"Part 2 solution: {fuel_cost.min()}")


from scipy.spatial import Delaunay, delaunay_plot_2d, Voronoi, voronoi_plot_2d
import matplotlib.pyplot as plt
import numpy as np

w = h = 360

n = 6
np.random.seed(0)
pts = np.random.randint(0, w, (n, 2))

print(pts)
# [[172  47]
#  [117 192]
#  [323 251]
#  [195 359]
#  [  9 211]
#  [277 242]]

print(type(pts))
# <class 'numpy.ndarray'>

print(pts.shape)
# (6, 2)

tri = Delaunay(pts)

print(type(tri))
# <class 'scipy.spatial.qhull.Delaunay'>

fig = delaunay_plot_2d(tri)
fig.savefig('data/dst/scipy_matplotlib_delaunay.png')
plt.close()

# ![data/dst/scipy_matplotlib_delaunay.png](data/dst/scipy_matplotlib_delaunay.png)

print(tri.points)
# [[172.  47.]
#  [117. 192.]
#  [323. 251.]
#  [195. 359.]
#  [  9. 211.]
#  [277. 242.]]

print(tri.points == pts)
# [[ True  True]
#  [ True  True]
#  [ True  True]
#  [ True  True]
#  [ True  True]
#  [ True  True]]

print(tri.simplices)
# [[0 1 4]
#  [1 3 4]
#  [5 0 2]
#  [5 1 0]
#  [3 5 2]
#  [5 3 1]]

print(pts[tri.simplices])
# [[[172  47]
#   [117 192]
#   [  9 211]]
#
#  [[117 192]
#   [195 359]
#   [  9 211]]
#
#  [[277 242]
#   [172  47]
#   [323 251]]
#
#  [[277 242]
#   [117 192]
#   [172  47]]
#
#  [[195 359]
#   [277 242]
#   [323 251]]
#
#  [[277 242]
#   [195 359]
#   [117 192]]]

vor = Voronoi(pts)

print(type(vor))
# <class 'scipy.spatial.qhull.Voronoi'>

fig = voronoi_plot_2d(vor)
fig.savefig('data/dst/scipy_matplotlib_voronoi.png')
plt.close()

# ![data/dst/scipy_matplotlib_voronoi.png](data/dst/scipy_matplotlib_voronoi.png)

print(vor.vertices)
# [[ 41.71518987  80.51265823]
#  [ 82.09150528 310.02013526]
#  [331.19719626  87.04766355]
#  [218.67630058 147.63583815]
#  [282.99117647 333.43398693]
#  [182.6014461  263.07537248]]

print(vor.regions)
# [[-1, 0, 1], [], [5, 3, 2, 4], [3, 0, -1, 2], [4, -1, 2], [5, 1, 0, 3], [5, 1, -1, 4]]

print([r for r in vor.regions if -1 not in r and r])
# [[5, 3, 2, 4], [5, 1, 0, 3]]

for region in [r for r in vor.regions if -1 not in r and r]:
    print(vor.vertices[region])
# [[182.6014461  263.07537248]
#  [218.67630058 147.63583815]
#  [331.19719626  87.04766355]
#  [282.99117647 333.43398693]]
# [[182.6014461  263.07537248]
#  [ 82.09150528 310.02013526]
#  [ 41.71518987  80.51265823]
#  [218.67630058 147.63583815]]

fig, ax = plt.subplots()
voronoi_plot_2d(vor, ax)

for region, c in zip([r for r in vor.regions if -1 not in r and r], ['yellow', 'pink']):
    ax.fill(vor.vertices[region][:, 0],
            vor.vertices[region][:, 1],
            color=c)

fig.savefig('data/dst/scipy_matplotlib_voronoi_fill.png')
plt.close()
# /usr/local/lib/python3.7/site-packages/scipy/spatial/_plotutils.py:20: MatplotlibDeprecationWarning: The ishold function was deprecated in version 2.0.
#   was_held = ax.ishold()

# ![data/dst/scipy_matplotlib_voronoi_fill.png](data/dst/scipy_matplotlib_voronoi_fill.png)

fig, ax = plt.subplots(figsize=(4, 4))
delaunay_plot_2d(tri, ax)
voronoi_plot_2d(vor, ax, show_vertices=False)

ax.set_xlim(0, w)
ax.set_ylim(0, h)
ax.grid(linestyle='--')

fig.savefig('data/dst/scipy_matplotlib_delaunay_voronoi.png')
plt.close()
# /usr/local/lib/python3.7/site-packages/scipy/spatial/_plotutils.py:20: MatplotlibDeprecationWarning: The ishold function was deprecated in version 2.0.
#   was_held = ax.ishold()

# ![data/dst/scipy_matplotlib_delaunay_voronoi.png](data/dst/scipy_matplotlib_delaunay_voronoi.png)


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

data = pd.read_csv("Salary_Data.csv")
#print(data.head())

X,y = data.iloc[:, 0],data.iloc[:, 1]
print(X,y)

#data visualisation

plt.scatter(X,y)
plt.show()

#inital declaration

m = 0
c = 0
l = 0.0001         #learning rate - this value should me minimum for a minimization problem
no_of_iter = 1000 #number of iteration required for reaching the global minimum point for optimizing the cost function
n = float(len(X))

for i in range(no_of_iter):
	y_pred = m*X + c
	#print(y_pred)
	d_m = (-2/n)*sum(X*(y - y_pred)) #partial derivation wrt slope
	d_c = (-2/n)*sum(y - y_pred)     #partial derivation wrt y-intercept
	m = m - l*d_m
	c = c - l*d_c

print(round(m,2),round(c,2)) #this is the required slope and intercept of the regression line

#---------------------------plottting regression line----------------------------------------------------

y_pred = m*X + c
plt.scatter(X, y)
plt.scatter(X, y_pred)
plt.show()

print("the required regression line:","y = ",round(m,2),"X + ",round(c,2))


import math
import numpy as np

def trunc_gaussmf(x, parameters):
    """
    Gaussian Truncated fuzzy membership function
    :param x: data point
    :param parameters: a list with 2 real values (mean and variance) and 2 limits
    :return: the membership value of x given the parameters
    """

    mean = parameters[0]
    var = parameters[1]
    lower_bound = parameters[2]
    upper_bound = parameters[3]
    coordinate_index = parameters[4]

    value = x[coordinate_index]
    if (value >= lower_bound) & (value <= upper_bound) :
        return math.exp((-(value - mean)**2)/(2 * var**2))
    else:
        return 0

def weighted_distance(x, parameters):
    centroids = parameters[0]
    cent_ind = parameters[1]
    m = 2

    n_clusters = len(centroids)

    dists = np.zeros(n_clusters)
    i = 0

    # Distance between instances and centroids
    for centroid in centroids:
        dists[i] = distance(x, centroid)
        i += 1

    # Update membership function
    return calculate_membership(dists[cent_ind], dists, m)

def distance(x, y):
    dist = [(a - b) ** 2 for a, b in zip(x, y)]
    return math.sqrt(sum(dist))

def calculate_membership(dist_inst_c, dists, m):

    # If distance is zero, instance is the centroid
    if dist_inst_c == 0:
        result = 1
    else:
        # instance is the centroid of another group
        if any(x == 0 for x in dists) :
            result = 0
        else:
            exp = 2/(m-1)
            result = 1 / sum([(dist_inst_c / x)**exp for x in dists])

    return result


import numpy as np
from numpy import array
from numpy import mean
from numpy.linalg import eig

D = array([[4, -1], [-2, 3]])
print("We have the data: \n D=")
print(D)
MU = mean(D.T, axis=1)
print("Step1: Compute the mean vector: \n mu =")
print(MU)
Z = D - MU
print("Step2: Subtract the mean from data: Z = X - MU \n Z =")
print(Z)
S = len(Z) * np.cov(Z.T)
print("Step3: Calculate the scatter matrix: \n S =")
print(S)
values, vectors = eig(S)
print("Step4: Compute the eigen vectors and eigen values.")
print("Eigen vectors (e_i):")
print(vectors)
print("Eigen values (lambda_i:")
print(values)
P = vectors.T.dot(Z.T)
print("Step5: Projected Data:")
print(P.T)


import numpy as np

def sigmoid(z, grad=False):
    return 1 / (1 + np.exp(-z)) if not grad else sigmoid(z) * (1 - sigmoid(z))

def relu(z, grad=False):
    if not grad:
        return np.maximum(z, 0)
    else:
        dz = np.zeros_like(z)
        for i in range(z.shape[1]):
            dz[:, i][z[:, i] > 0] = 1
        return dz

def softmax(z):
    exp = np.exp(z)
    return exp / exp.sum(axis=0)

registry = {
    "relu": relu,
    "sigmoid": sigmoid
}


import numpy as np

def lerp(a, b, t):
    return a * (1 - t) + b * t

def normalize(vector):
    return vector / np.linalg.norm(vector)

def random_unit_vector():
    point = np.random.rand(3)
    while np.dot(point, point) >= 1:
        point = np.random.rand(3)
    return normalize(point)


import numpy as np
import pandas as pd
import scipy
from sklearn.model_selection import KFold

root = '../../'
import sys
sys.path.append(root+"pylib")
import tool
import data

import entropyV21 as entropy
from GaussianNaiveClassifier import NaiveClassifier

# read data
dataset_location = root+"dataset/ionosphere_org_33.csv"
dataset_location = root+"dataset/Iris.csv"

X, y= data.read_csv(dataset_location, shuffle=False)
n, m = X.shape
print(X.shape)

k = 1 # reduced dimension

f = n # LEAVE ONE OUT
seed = -1
# split
if seed < 0:
    kf = KFold(n_splits = f, shuffle = True)
else:
    kf = KFold(n_splits = f, random_state = seed, shuffle = True)
idxesLists = kf.split(X)
splits = []
for trainidx, testindx in idxesLists:
    splits.append((trainidx, testindx))

DEBUG = True
if DEBUG:
    accs_imp = 0
    accs_imp_reduce = 0

    for trainidx, testindx in splits:
        X_train = X[trainidx,:]
        y_train = y[trainidx]
        X_test = X[testindx,:]
        y_test = y[testindx]

        Xt_train = X_train.T
        Xt_test = X_test.T

        #1.preprocessing
        # remove mean
        mean = np.mean(Xt_train,1).reshape(m,-1)
        Xt_train = Xt_train - mean
        Xt_test = Xt_test - mean
        X_train = Xt_train.T
        X_test  = Xt_test.T

        # PCA: dimension reduction
        U, Wt_train, _, _ = entropy.qwPCA(Xt_train, k)

        W_train = Wt_train.T
        Wt_test = U.T@Xt_test
        W_test = Wt_test.T

        #2. TEST
        # my implementation: without PCA
        clf = NaiveClassifier()
        clf.fit(X_train, y_train)
        y_pre = clf.predict(X_test)

        diff = y_pre - y_test
        acc = 1 - np.count_nonzero(diff)/len(y_test)
        accs_imp += acc

        # my implementation: with PCA
        clf = NaiveClassifier()
        clf.fit(W_train, y_train)
        y_pre = clf.predict(W_test)

        diff = y_pre - y_test
        acc = 1 - np.count_nonzero(diff)/len(y_test)
        accs_imp_reduce += acc

    print('accs_imp     :',accs_imp/f)
    print('accs_imp pca :',accs_imp_reduce/f)


"""
Credit: mholtrop
Edited by: npgh2009
"""

from matplotlib import pyplot as plt
import numpy as np
import scipy.sparse as sp
from scipy.sparse.linalg import eigs

#initialize harmonic oscillator parameters
hbar=1
m=1
omega=1

#initialize x grid
N = 200 # grid points
a = 20.0 # x limits
x = np.linspace(-a/2.,a/2.,N)
dx = x[1]-x[0] # step

#Potential
V = .5*m*omega*x*x
# V[N/2]=2/dx   # This would add a "delta" spike in the center.

# Construct hamiltonian matrix
DerivativeTerm = 1/(dx*dx)*sp.diags([1, -2, 1], [-1, 0, 1], shape=(N, N))
Hamiltonian = -(hbar*hbar)/(2.0*m)*DerivativeTerm + sp.diags(V)

En,psiT = eigs(Hamiltonian) # This computes the eigen values and eigenvectors
psi = np.transpose(psiT)
# The psi now contain the wave functions ordered so that psi[n] if the n-th eigen state.

#Check the normalization of the wave function arrays.
notok=False
for n in range(len(psi)):
    # s = np.sum(psi[n]*psi[n])
    s = np.linalg.norm(psi[n])  # This does the same as the line above.
    if np.abs(s - 1) > 0.00001: # Check if it is different from one.
        print("Wave function {} is not normalized to 1 but {}".format(n,s))
        notok=True

if not notok:
    print("All the psi_n(x) are normalized.")

fig2 = plt.figure(figsize=[10,7])
plt.title('Harmonic Oscillator')
plt.ylabel('$\psi(x)$')
plt.xlabel('$x$')
#plt.plot([0,0],[-6,V[0]],color="blue")
#plt.plot([-a/2.,a/2.],[0,0],color="blue")
plt.plot(x, 0.1*V, color="grey", label="V(x) scaled by 0.1")

plt.ylim(-1,1)
plt.xlim(-6,6)

for i in range(5):
    if psi[i][int(N/8)] < 0:
        plt.plot(x,-abs(psi[i])/np.sqrt(dx),label="$E_{}$={:3.1f}".format(i,En[i]))
    else:
        plt.plot(x,abs(psi[i])/np.sqrt(dx),label="$E_{}$={:3.1f}".format(i,En[i]))

plt.title("Solution to harmonic oscillator")
plt.legend()
plt.show()


import numpy as np

f = open('p102_text.txt')
fr = f.readline()

triangles = []
while fr:
    fs = (fr.strip()).split(',')
    triangles.append([[int(fs[0]),int(fs[1])],
                     [int(fs[2]),int(fs[3])],
                     [int(fs[4]),int(fs[5])]])
    fr = f.readline()

# By using cross products, we can test if two points lie on
# the same side of a line (if they both point in same direction,
# i.e. their dot product is greater than or equal to zero).  Using this,
# we can test to see if a given point is on the same side of the line AB
# as the third point of the triangle, C.  Permute this, and if they are all true
# then we are good to go.

def cross_product(a,b):
    return a[0]*b[1] - b[0]*a[1]

def same_side(p1,p2,a,b):
    b_minus_a = [b[i] - a[i] for i in range(len(a))]
    p1_minus_a = [p1[i] - a[i] for i in range(len(a))]
    p2_minus_a = [p2[i] - a[i] for i in range(len(a))]
    cross_prod_1 = cross_product(b_minus_a, p1_minus_a)
    cross_prod_2 = cross_product(b_minus_a, p2_minus_a)
    return cross_prod_1 / abs(cross_prod_1) == cross_prod_2 / abs(cross_prod_2)

def in_triangle(p, tri):
    res_1 = same_side(p,tri[0],tri[1],tri[2])
    res_2 = same_side(p,tri[1],tri[0],tri[2])
    res_3 = same_side(p,tri[2],tri[0],tri[1])
    if res_1 == res_2 == res_3 == True:
        return 1
    else:
        return 0

s = 0
for tri in triangles:
    s += in_triangle([0,0], tri)
print s


import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from scipy.integrate import odeint
import time as pctime

#  load data

print('Loading data')

data = pd.read_csv('https://github.com/pcm-dpc/COVID-19/raw/master/dati-andamento-nazionale/dpc-covid19-ita-andamento-nazionale.csv')
xdata=pd.to_numeric(range(data.shape[0]))
ydata=data['totale_casi']
ydata_death=data['deceduti']
ydata_rec=data['dimessi_guariti']

ydata_inf=ydata-ydata_rec-ydata_death

### definition of SIR 1.0

print('Initialization of SIR models')

# The SIR model differential equations.
def deriv_SIR(y, t, N, beta,gamma):
    S,I,R = y

    dSdt = -(beta*I/N)*S
    dIdt = (beta*S/N)*I - gamma*I
    dRdt = gamma*I

    return dSdt, dIdt, dRdt

def SIR(N,beta,gamma,I0=1,R0=0,t=np.arange(0,365)):
    # Definition of the initial conditions
    # I0 and R0 denotes the number of initial infected people (I0)
    # and the number of people that recovered and are immunized (R0)

    # t ise the timegrid

    S0=N-I0-R0  # number of people that can still contract the virus

    # Initial conditions vector
    y0 = S0, I0, R0

    # Integrate the SIR equations over the time grid, t.
    ret = odeint(deriv_SIR, y0, t, args=(N,beta,gamma))
    S, I, R = np.transpose(ret)

    return (t,S,I,R)

# ### definition of SIR 2.0

# The SIR model differential equations.
def deriv_SIR_2(y, t, N, beta1,gamma,tau=10**6,t_thresh=14):
    S,I,R = y

    if t<=t_thresh:      # il lockdown nazionale inizia al 14° giorno
        B=beta1
    else:
        B=beta1*np.exp(-(t-t_thresh)/tau)

    dSdt = -(B*I/N)*S
    dIdt = (B*S/N)*I - gamma*I
    dRdt = gamma*I

    return dSdt, dIdt, dRdt

def SIR_2(N,beta1,gamma,tau=10**6,t_thresh=14,I0=1,R0=0,t=np.arange(0,365)):
    # Definition of the initial conditions
    # I0 and R0 denotes the number of initial infected people (I0)
    # and the number of people that recovered and are immunized (R0)

    # t ise the timegrid

    S0=N-I0-R0  # number of people that can still contract the virus

    # Initial conditions vector
    y0 = S0, I0, R0

    # Integrate the SIR equations over the time grid, t.
    ret = odeint(deriv_SIR_2, y0, t, args=(N,beta1,gamma,tau,t_thresh))
    S, I, R = np.transpose(ret)

    return (t,S,I,R)

# # fitting the active infected

print('Fitting the model')

# 3 parameter fit for the active infected

def optimizer_adv(R0,tau,t_thresh):

    asympt=3

    fin_result_updated=SIR_2(6*10**7,R0*1/21,1/21,tau,t_thresh,I0=asympt*ydata_inf[0])
    i_vec=fin_result_updated[2]/asympt

    pesi=np.exp(-np.arange(len(ydata_inf))/7)    #
    pesi=pesi[::-1]

    accuracy=np.sum((ydata_inf-i_vec[0:len(ydata_inf)])**2)   #mean squared error. This is used for the optimization

    errperc=np.mean(np.abs((ydata_inf-i_vec[0:len(ydata_inf)])/ydata_inf))*100
    stdperc=np.std(np.abs((ydata_inf-i_vec[0:len(ydata_inf)])/ydata_inf))*100

    return accuracy,errperc,stdperc

# grid on 3 parameters
R0grid=np.linspace(7.5,8.5,50)
taugrid=np.linspace(25,27,200)
#ttreshgrid=np.linspace(0,10,15)

res_scan=[]
counter=0
counter2=0
cycle_tot=len(R0grid)*len(taugrid) #*len(ttreshgrid)

time1=pctime.time()

# minimization

for r in R0grid:
    for tau in taugrid:
        opt_res=optimizer_adv(r,tau,0)
        res_scan.append([r,tau,0,opt_res[0],opt_res[1],opt_res[2]])
        counter=counter+1
        counter2=counter2+1
        if counter2==cycle_tot/10:
            time2=pctime.time()
            remtime=round((time2-time1)/counter*(cycle_tot-counter),1)
            print('completed ',round(counter/cycle_tot*100,1),'%. Remaining time ',remtime,'sec')
            counter2=0

res_scan=np.array(res_scan)

df_res_scan=pd.DataFrame(res_scan)
df_res_scan.columns=['R0','tau','t_thresh','MSE','mean err%','std err%']

print(df_res_scan.sort_values(by='MSE').head())

par_ideal=np.array(df_res_scan.sort_values(by='MSE').iloc[0,0:])

fin_result_updated=SIR_2(6*10**7,par_ideal[0]*1/21,1/21,par_ideal[1],t_thresh=par_ideal[2],I0=3*ydata_inf[0])

t=fin_result_updated[0]
s_vec=fin_result_updated[1]
i_vec=fin_result_updated[2]
r_vec=fin_result_updated[3]

plt.figure(figsize=(7,5))
plt.plot(np.arange(len(ydata_inf)),ydata_inf,color='red',label='Active infected (data)')
plt.plot(t, i_vec/3, label='Active infected (model, best-fit)',color='blue',linestyle='--')
#plt.fill_between(t, i_vec*(1+par_ideal[5]/100*2.65)/3,i_vec*(1-par_ideal[5]/100*2.65)/3, label='Active infected (model, 99% of data)',color='blue',alpha=.2)
plt.plot(np.zeros(2)+70,[-1000,250000],color='purple')
plt.xticks(np.arange(0,100,7),['24 Feb','2 Mar','9 Mar','16 Mar','23 Mar','30 Mar','6 Apr','13 Apr','20 Apr','27 Apr','4 Mag','11 Mag','18 Mag','25 Mag','1 Giu'],rotation=30)
plt.xlim(0,100)
plt.ylim(100,2*10**5)
#plt.yscale('log')
plt.annotate("Lockdown", xy=(14,10000), xytext=(3,40000), arrowprops=dict(arrowstyle="->"),fontsize=13)
plt.xlabel('Data')
plt.ylabel('Counter')
plt.yscale('log')
plt.legend()
plt.grid(color='gray', linestyle='--', linewidth=0.5)
plt.tight_layout()
plt.savefig('output/fit_con_incertezza.png',dpi=300)
#plt.show()

print('Figure model-data saved')

#export

t_date=pd.to_datetime(t,unit='D',origin=pd.Timestamp('2020-02-24'))

export_v2 = pd.DataFrame({'date':t_date,'t':t,'s':s_vec,'i':i_vec,'r':r_vec})
export_v2.to_csv('output/nazionale.csv',index=False)

# # computation of national R0

# ### using data of last 5 days

today=len(xdata)

print('Computing R0 as function of time')

def minimizer(R0,t1=today-5,t2=today):

    #true data
    ydata_inf_2=np.array(ydata_inf[t1:t2])
    xdata_2=np.arange(0,len(ydata_inf_2))

    #print(ydata_inf_2)

    #model
    fin_result=SIR(60*10**6,1/14*R0,1/14,I0=ydata_inf_2[0])
    i_vec=fin_result[2]
    i_vec_2=i_vec[0:len(xdata_2)]

    #average error
    error=np.sum(np.abs(ydata_inf_2-i_vec_2)/ydata_inf_2)*100

    return error

minimizer_vec=np.vectorize(minimizer)

# ### scan of R0 over time

time_window=5

def minimizer_gen(t1,t2,xgrid=np.arange(0.1,5,0.01)):

    ygrid=minimizer_vec(xgrid,t1=t1,t2=t2)
    r0_ideal=round(xgrid[np.argmin(ygrid)],2)

    return r0_ideal

r0_time=[]
scangrid=np.linspace(0,5,100)

for i in range(0,today-(time_window-1)):
    min_val=minimizer_gen(i,i+time_window,xgrid=scangrid)
    r0_time.append(min_val)
    scangrid=np.linspace(0,min_val*2,100)  #the grid change over the time (this speed up the process)
    print('Day n',i,' R0=',min_val)
    print(i,i+time_window,len(ydata_inf))

r0_time=np.array(r0_time)

plt.figure(figsize=(5,5))
plt.plot(r0_time)
plt.xticks(np.arange(0-(time_window-5),80,7),['28 Feb','6 Mar','13 Mar','20 Mar','27 Mar','3 Apr','10 Apr','17 Apr','24 Apr','1 Mag','8 Mag','15 Mag'],rotation=20)
plt.xlim(0,today-4)
#plt.xlim(19,today-9)
plt.ylabel('$R_0$')
plt.ylim(0,5)
plt.grid()
plt.title('Evolution of $R_0$')
plt.savefig('output/r0-evo.png',dpi=300)
#plt.show()

print('Figure R0 saved')

# export R0 over time

df_r0=pd.DataFrame(pd.to_datetime(np.arange(len(r0_time)),unit='D',origin='2020-02-28'))
df_r0['R0']=r0_time
df_r0.columns=['Data','R0']

df_r0.to_csv('output/r0.csv',index=False)

# # Future forecasting

print('Future predictions as function of R0')

# The SIR model differential equations.
def deriv_SIR_2_future(y, t, N, beta1,gamma,newR0,tau=10**6,t_thresh=14):
    S,I,R = y

    if t<=t_thresh:      # il lockdown nazionale inizia al 14° giorno
        B=beta1
    elif t>t_thresh and t<=70:
        B=beta1*np.exp(-(t-t_thresh)/tau)
    elif t>70:
        B=newR0*gamma
        #B=beta1*np.exp(-(70-t_thresh)/tau)+0.05*gamma*(t-70)
        #print(B,t)

    dSdt = -(B*I/N)*S
    dIdt = (B*S/N)*I - gamma*I
    dRdt = gamma*I

    return dSdt, dIdt, dRdt

def SIR_2_future(N,beta1,gamma,newR0,tau=10**6,t_thresh=14,I0=1,R0=0,t=np.arange(0,365)):
    # Definition of the initial conditions
    # I0 and R0 denotes the number of initial infected people (I0)
    # and the number of people that recovered and are immunized (R0)

    # t ise the timegrid

    S0=N-I0-R0  # number of people that can still contract the virus

    # Initial conditions vector
    y0 = S0, I0, R0

    # Integrate the SIR equations over the time grid, t.
    ret = odeint(deriv_SIR_2_future, y0, t, args=(N,beta1,gamma,newR0,tau,t_thresh))
    S, I, R = np.transpose(ret)

    return (t,S,I,R)

asympt=3

i_vec_future050=SIR_2_future(6*10**7,par_ideal[0]*1/21,1/21,0.5,par_ideal[1],t_thresh=par_ideal[2],I0=asympt*ydata_inf[0])[2]
i_vec_future100=SIR_2_future(6*10**7,par_ideal[0]*1/21,1/21,1.0,par_ideal[1],t_thresh=par_ideal[2],I0=asympt*ydata_inf[0])[2]
i_vec_future110=SIR_2_future(6*10**7,par_ideal[0]*1/21,1/21,1.1,par_ideal[1],t_thresh=par_ideal[2],I0=asympt*ydata_inf[0])[2]
i_vec_future120=SIR_2_future(6*10**7,par_ideal[0]*1/21,1/21,1.20,par_ideal[1],t_thresh=par_ideal[2],I0=asympt*ydata_inf[0])[2]

plt.figure(figsize=(7,5))
plt.plot(np.arange(len(ydata_inf)),ydata_inf,color='red',linestyle='None',marker='.',label='Infetti sintomatici attivi (dati)')
plt.fill_between(t, i_vec_future100/asympt,i_vec_future050/asympt,color='green',label='Modello, $R_0$ fra 0.5 e 1',alpha=0.5)
plt.fill_between(t, i_vec_future110/asympt,i_vec_future100/asympt,color='orange',label='Modello, $R_0$ fra 1 e 1.1',alpha=0.5)
plt.fill_between(t, i_vec_future120/asympt,i_vec_future110/asympt,color='red',label='Modello, $R_0$ fra 1.1 e 1.2',alpha=0.5)
#plt.plot(t, i_vec_future05/asympt, label='Modello, R$_0^{riapertura}$=0.5')
#plt.plot(t, i_vec_future10/asympt, label='Modello, R$_0^{riapertura}$=1')
#plt.plot(t, i_vec_future15/asympt, label='Modello, R$_0^{riapertura}$=1.1')
#plt.plot(t, i_vec_future20/asympt, label='Modello, R$_0^{riapertura}$=1.2')
#plt.fill_between(t, i_vec_future*(1+par_ideal[4]/100*2)/asympt,i_vec_future*(1-par_ideal[4]/100*2)/asympt, label='Infetti attivi (modello, 95% C.L.)',color='red',alpha=.2)
plt.plot(np.zeros(2)+70,[-1000,10**7],color='purple')
plt.xticks(np.arange(6,360,30),['1 Mar','1 Apr','1 Mag','1 Giu','1 Lug','1 Ago','1 Set','1 Ott','1 Nov','1 Dic','1 Gen','1 Feb'],rotation=30)
plt.xlim(0,360)
plt.ylim(100,ydata_inf.max()*4.3)
#plt.ylim(100,10**7)
#plt.yscale('log')
plt.annotate("Lockdown", xy=(14,ydata_inf.max()*0.1), xytext=(3,ydata_inf.max()*2), arrowprops=dict(arrowstyle="->"),fontsize=13)
plt.annotate("Riapertura", xy=(70,ydata_inf.max()), xytext=(80,ydata_inf.max()*2), arrowprops=dict(arrowstyle="->"),fontsize=13)
plt.xlabel('Data')
plt.ylabel('Counter')
plt.legend()
plt.grid(color='gray', linestyle='--', linewidth=0.5)
plt.title('2 asintomatici per ogni sintomatico')
plt.tight_layout()
plt.savefig('output/predizioni_future.png',dpi=300)
#plt.show()

print('Figure prediction saved')

#export

ydata_inf_toexport=np.empty(len(i_vec))
ydata_inf_toexport[0:len(ydata_inf)]=ydata_inf
ydata_inf_toexport[len(ydata_inf):]=np.nan

t_date=pd.to_datetime(t,unit='D',origin=pd.Timestamp('2020-02-24'))

export_forecast = pd.DataFrame({'date':t_date,'t':t,'R0=0.5':i_vec_future050/asympt,'R0=1':i_vec_future100/asympt,'R0=1.1':i_vec_future110/asympt,'R0=1.2':i_vec_future120/asympt,'infetti_reali':ydata_inf_toexport})
export_forecast.to_csv('output/predizioni_future_export.csv',index=False)


import numpy as np
from math import sqrt
from data import generate_data_line, plot_generated_data
import matplotlib.pyplot as plt

def plot_data(x, y, LR, name):
    plt.scatter(x, y)
    # plt = abline(LR.m, LR.c, plt)
    # axes = plt.gca()
    x_vals = np.array([x.min(), x.max()])
    y_vals = LR.m * x_vals + LR.c
    plt.plot(x_vals, y_vals, "--")
    plt.savefig("images/" + name)
    plt.clf()
    return

class LinearReg:
    """ A bi-variable linear regressor class """

    def __init__(self, m=np.random.randint(0, 5), c=np.random.randint(0, 5), lr=0.1):
        """initialize the class with:
        slope(m), intercept(c) and learning rate(lr)"""
        self.m = m
        self.c = c
        self.lr = lr
        # print(f"Initialized with LR.m: {self.m:.4f}, LR.c: {self.c:.4f}, lr: {self.lr:.4f}")

    def mean_squared_error(self, y, pred_y):
        """Calculate the MSE for vectors

        Args:
            y (np.array): actual y values
            pred_y (np.array): predicted y values

        Returns:
            float: the MSE from y and pred_y
        """
        return sqrt(np.mean((y - pred_y) ** 2))

    def update_parameters(self, err, x):
        N = x.shape[0]
        dm = (2.0 / N) * (-np.sum(np.multiply(x, (err))))
        dc = (2.0 / N) * (-np.sum(err))
        # print(dm, dc)
        self.m = self.m - (self.lr * dm)
        self.c = self.c - (self.lr * dc)
        return

    def train(self, x, y, epochs=501):
        cost_history = []
        for epoch in range(epochs):
            pred_y = self.m * x + self.c
            err = y - pred_y
            self.update_parameters(err, x)

            cost = self.mean_squared_error(y, pred_y)
            cost_history.append(cost)

            if epoch % 100 == 0:
                print(f"LR.m: {self.m:.4f}, LR.c: {self.c:.4f}, cost: {cost:.4f}")
                name = str(epoch) + "_epoch.png"
                plot_data(x, y, self, name)

        return cost_history

if __name__ == "__main__":
    data = generate_data_line(num=10)
    x, y = np.array(list(zip(*data)))
    plot_generated_data(x, y)

    LR = LinearReg(m=np.mean(x), c=np.mean(y))
    cost_history = LR.train(x, y)

    print(LR.m)
    print(LR.c)

    plt.plot(cost_history)
    plt.savefig("images/cost_history.png")


import numpy as np
import random
import math

def normaliseList(ll,max_value=10.):
    minv = min(ll)
    maxv = max(ll)

    new_ll = [(x-minv)*max_value/maxv for x in ll]

    return new_ll

def sigmoid(x,temp=1.):
    return 1.0/(1.+math.exp(-x/temp))

def softmaxSample(value_list,strict,softmax_list=[]):
    if len(softmax_list) == 0:
        softmax_list = getSoftmaxList(value_list,strict)

    pointer = random.random()*sum(softmax_list)
    tier = 0
    idx = 0

    for value in softmax_list:
        if pointer >= tier and pointer < tier+value:
            return idx
        else:
            tier += value
            idx += 1
    return -1

def getSoftmaxList(value_list, strict):
    softmax_list = []
    for value in value_list:
        softmax_list.append(np.exp(value/strict))
    return softmax_list


import numpy as np
import matplotlib.pyplot as plt
#Heat equation
A1 = np.array([[4,-1,0,-1,0,0,0,0,0],
 [-1,4,-1,0,-1,0,0,0,0],
 [0,-1,4,0,0,-1,0,0,0],
 [-1,0,0,4,-1,0,-1,0,0],
 [0,-1,0,-1,4,-1,0,-1,0],
 [0,0,-1,0,-1,4,0,0,-1],
 [0,0,0,-1,0,0,4,-1,0],
 [0,0,0,0,-1,0,-1,4,-1],
 [0,0,0,0,0,-1,0,-1,4]])
b= np.array([0,0,100,0,0,100,200,200,300])
T = np.matmul(np.linalg.inv(A1),b)
print("Temprature at given points:",T)
Z = np.array([[0,0,0,0,50],
 [0,T[0],T[1],T[2],100],
 [0,T[3],T[4],T[5],100],
 [0,T[6],T[7],T[8],100],
 [100,200,200,200,150]])
plt.imshow(Z)
plt.colorbar(label="Temprature")
plt.title('Heat Map of temperatures at defined points')
plt.show()
#1-D wave equation
A=np.linalg.inv(np.array([[4,-1,0,0],
 [-1,4,-1,0],
 [0,-1,4,-1],
 [0,0,-1,4]]))
Tj0= np.array([np.sin(0.4*np.pi),
 np.sin(0.2*np.pi)+np.sin(0.6*np.pi),
np.sin(0.4*np.pi)+np.sin(0.8*np.pi),
np.sin(0.6*np.pi)])
Tu1=np.matmul(A,Tj0)
u11,u21,u31,u41=Tu1
print("\n"+"Tempratures at t= 0.04:",Tu1)
Tj1=np.array([u21,u31+u11,u41+u21,u31])
u12,u22,u32,u42=np.matmul(A,Tj1)
Tu2=np.array([u12,u22,u32,u42])
print("Tempratures at t= 0.08:",Tu2)
Tj2=np.array([u22,u12+u32,u22+u42,u32])
u13,u23,u33,u43=np.matmul(A,Tj2)
Tu3=np.array([u13,u23,u33,u43])
print("Tempratures at t= 0.12:",Tu3)
Tj3=np.array([u23,u13+u33,u23+u43,u33])
u14,u24,u34,u44=np.matmul(A,Tj3)
Tu4=np.array([u14,u24,u34,u44])

print("Tempratures at t= 0.16:",Tu4)
Tj4=np.array([u24,u14+u34,u24+u44,u34])
u15,u25,u35,u45=np.matmul(A,Tj4)
Tu5=np.array([u15,u25,u35,u45])
print("Tempratures at t= 0.20:",Tu5)
#The border points are =0 meaning that
#appending them on will give the correct
#result when plotted
u1=np.append([0],np.append(Tu1,[0]))
u2=np.append([0],np.append(Tu2,[0]))
u3=np.append([0],np.append(Tu3,[0]))
u4=np.append([0],np.append(Tu4,[0]))
u5=np.append([0],np.append(Tu5,[0]))
x=np.arange(0,1.2,0.2)
plt.plot(x,u1,label='t=0.04',c='k')
plt.scatter(x,u1,c='k')
plt.plot(x,u2,label='t=0.08',c='b')
plt.scatter(x,u2,c='b')
plt.plot(x,u3,label='t=0.12',c='g')
plt.scatter(x,u3,c='g')
plt.plot(x,u4,label='t=0.16',c='y')
plt.scatter(x,u4,c='y')
plt.plot(x,u5,label='t=0.20',c='c')
plt.scatter(x,u5,c='c')
plt.title("Temperature against distance with varying times")
plt.ylabel("Temprature")
plt.xlabel("Distance")
plt.legend(loc=0)
plt.show()


import numpy as np
from scipy.stats import norm, multivariate_normal, bernoulli
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
from sklearn.model_selection import train_test_split

def generate_data(n, alpha0, alpha1A, alpha1B, time_steps):
    b_0, b_1 = multivariate_normal.rvs(mean=np.zeros(2), cov=np.array([[1, 0.5],[0.5, 1]]), size=n).transpose()
    t = np.arange(time_steps)
    epsilon = norm.rvs(loc=0, scale=0.2, size=n*time_steps)

    Y_A = []
    Y_B = []
    for i in range(n):
        if(i < n/2):
            new_individual = alpha0 + b_0[i] + (alpha1A + b_1[i]) * t + epsilon[time_steps*i : time_steps*i + time_steps]
            Y_A.append(new_individual)
        else:
            new_individual = alpha0 + b_0[i] + (alpha1B + b_1[i]) * t + epsilon[time_steps*i : time_steps*i + time_steps]
            Y_B.append(new_individual)

    data = Y_A + Y_B
    labels = np.append(np.ones(n//2), np.ones(n//2)*0) #A:1, B:0
    return (data, labels)

def generate_data_MCAR(data, p):
    data_ = np.array(data[0])
    labels = data[1]
    time_steps = len(data_[0])
    n = len(data_)
    miss_positions = np.reshape(bernoulli.rvs(p, size=n*time_steps), (n, time_steps))
    data_[miss_positions==1] = None
    return (data_, labels)

def generate_data_MAR(data, p_A, p_B):
    data_ = np.array(data[0])
    labels = data[1]

    dataA = data_[labels==1]
    time_stepsA = len(dataA[0])
    nA = len(dataA)
    miss_positionsA = np.reshape(bernoulli.rvs(p_A, size=nA*time_stepsA), (nA, time_stepsA))
    dataA[miss_positionsA==1] = None
    labelsA = np.ones(nA)

    dataB = data_[labels==0]
    time_stepsB = len(dataB[0])
    nB = len(dataB)
    miss_positionsB = np.reshape(bernoulli.rvs(p_B, size=nB*time_stepsB), (nB, time_stepsB))
    dataB[miss_positionsB==1] = None
    labelsB = np.zeros(nB)

    data_ = np.append(dataA, dataB)
    labels = np.append(labelsA, labelsB)

    return (data_, labels)

def generate_data_MNAR(data, p_A, p_B, treshold):
    data_ = np.array(data[0])
    labels = data[1]

    dataA = np.array(data_[labels==1])
    time_stepsA = len(dataA[0])
    nA = len(dataA)
    miss_positionsA = np.reshape(bernoulli.rvs(p_A, size=nA*time_stepsA), (nA, time_stepsA))
    dataA[miss_positionsA==1] = None
    dataA[dataA >= treshold] = None
    labelsA = np.ones(nA)

    dataB = data_[labels==0]
    time_stepsB = len(dataB[0])
    nB = len(dataB)
    miss_positionsB = np.reshape(bernoulli.rvs(p_B, size=nB*time_stepsB), (nB, time_stepsB))
    dataB[miss_positionsB==1] = None
    dataA[dataB >= treshold] = None
    labelsB = np.zeros(nB)

    data_ = np.append(dataA, dataB)
    labels = np.append(labelsA, labelsB)

    return (data_, labels)

def CCA(data):
    data_ = data[0]
    labels = data[1]
    dataCCA = [l for l in data_ if not np.isnan(l).any()]
    labelsCCA = [labels[i] for i in range(len(data_)) if not np.isnan(data_[i]).any()]
    return (dataCCA, labelsCCA)

def LOCF(data):
    pass

def mean_imputation(data):
    pass

def regression_imputation(data):
    pass

def multiple_imputation(data):
    pass


"""
Summarize primes
http://www.rosettacode.org/wiki/Summarize_primes
"""

import itertools
import sympy

def get_subseq(n: int):
    # prime list [2, n)
    primes = list(sympy.primerange(n))
    # cummulative sum list of primes
    cum_primes = list(itertools.accumulate(primes))
    # Internally primes exntends to [2, sum of primes in range [2, n)]
    # to see if sum of items in primes is also prime
    primes = primes + list(sympy.primerange(n, sum(primes)))

    subseqs = []
    for idx, val in enumerate(cum_primes):
        if val in primes:  # if cumulative sum is also prime
            # (length of subseq, last prime num in subseq, sum of subseq)
            subseq = (idx + 1, primes[idx], val)
            subseqs.append(subseq)

    return subseqs

def main():
    rst = get_subseq(1000)
    print("prime   last  prime")
    print("count  prime    sum")
    for item in rst:
        sb = f"{item[0]:5d}  {item[1]:5d}  {item[2]:5d}"
        print(sb)

if __name__ == "__main__":
    main()


import numpy as np

def accuracy(ytrue: np.ndarray, ypred: np.ndarray):
    return np.sum(ytrue == ypred) / ytrue.size

def error_rate(ytrue: np.ndarray, ypred: np.ndarray):
    return np.sum(ytrue != ypred) / ytrue.size

def mean_squared_error(ytrue: np.ndarray, ypred: np.ndarray):
    return np.sum((ytrue - ypred) ** 2) / ytrue.size

def rooted_mean_squared_error(ytrue: np.ndarray, ypred: np.ndarray):
    return np.sqrt(np.sum((ytrue - ypred) ** 2) / ytrue.size)

def f1_score(ytrue: np.ndarray, ypred: np.ndarray):
    tp = np.sum(np.logical_and(ytrue == 1, ypred == 1))
    recall = tp / np.sum(ytrue == 1)
    prec = tp / np.sum(ypred == 1)
    return 2 * prec * recall / (prec + recall)


"""Transformation Functions"""

# Authors: Jeffrey Wang
# License: BSD 3 clause

import numpy as np
from scipy import stats

def log_transform(data, base=np.e, axis=0):
	"""
	Transform the data into a logarithm.

	Parameters
	----------
	data : ndarray
		Data to be log transformed.

	base : {scalar, 'mean', 'median'}, default=np.e
		Log base for normalization. Must be one of:
		 - scalar : Constant base.
		 - 'mean' : Set the base to the mean of the data.
		 - 'median' : Set the base to the median of the data.

	axis : int, default=0
		Axis to transform along.

	Returns
	-------
	transform : ndarray
		Log transformed data.
	"""
	if base == 'mean':
		base = np.mean(data, axis=axis)
	elif base == 'median':
		base = np.median(data, axis=axis)
	return np.log(data) / np.log(base)

def boxcox_transform(data, lmbda=None):
	"""
	Transform the data by a Box-Cox power transformation.

	Parameters
	----------
	data : ndarray
		Data to be transformed.

	lmbda : scalar, default=np.e
		If lmbda is not None, do the transformation for that value.
		If lmbda is None, find the lambda that maximizes
		the log-likelihood function and return it as the
		second output argument.

	Returns
	-------
	transform : ndarray
		Transformed data.

	maxlog : float, optional
		If the lmbda parameter is None, maxlog is
		the lambda that maximizes the log-likelihood function.
	"""
	return stats.boxcox(data, lmbda=lmbda)

def power_transform(data, a):
	"""
	Transform the data into by a power.

	Parameters
	----------
	data : ndarray
		Data to be power transformed.

	a : scalar
		Exponent to use for transformation.

	Returns
	-------
	transform : ndarray
		Power transformed data.
	"""
	return np.sign(data) * np.power(np.absolute(data), a)


from statsmodels.nonparametric.kde import KDEUnivariate
import matplotlib.pyplot as plt
import numpy as np

kernels = ['gau', 'epa', 'uni', 'tri', 'biw', 'triw']
kernels_names = ['Gaussian', 'Epanechnikov', 'Uniform', 'Triangular', 'Biweight', 'Triweight']
positions = np.arange(1,9,1)

fig, ax = plt.subplots()

for kernel, kernel_name, pos in zip(kernels, kernels_names, positions):

    # kernels
    kde = KDEUnivariate([0])
    kde.fit(kernel= kernel, bw=1,  fft=False, gridsize=2**10)
    ax.plot(kde.support, kde.density, label = kernel_name, linewidth=1.5, alpha=0.8)

ax.set_xlim(-2,2)
ax.grid()
ax.legend(title='kernel functions')


from numpy import array # pip install numpy
from pprint import pprint # pip install pprint

#################
#   Functions   #
#################
def mod3(arg):
    return arg % 3

def weight(word):
    count = 0
    for i in word:
        if i != 0: count += 1
    return count

def d(word1, word2):
    if len(word1) != len(word2): return 0
    return weight([word1[i] - word2[i] for i in range(len(word1))])

def code(g):
    return array(
        [
            mod3(vec) for vec in [
                g[0] + g[0] + g[0],
                g[0],
                g[1],
                g[0] + g[0],
                g[1] + g[1],
                g[0] + g[1],
                g[0] + g[0] + g[1],
                g[0] + g[1] + g[1],
                g[0] + g[0] + g[1] + g[1],
            ]
        ]
    )

def dot(v1, v2):
    prod = 0
    if len(v1) == len(v2):
        for i in range(len(v1)):
            prod += v1[i] * v2[i]
    return prod

def matMul(m1, m2):
    return array([[dot(m, n) for m in m2] for n in m1])

def test(testCodeWord, ParityCheckMatrix, silent = False):
    syndrome = [dot(v, testCodeWord) for v in ParityCheckMatrix]
    if not silent:
        pprint('Test code:')
        pprint(testCodeWord)

        pprint('Syndrome:')
        pprint(mod3(array(syndrome)))

    return mod3(array(syndrome))

def minD(code):
    weightList = []
    ncode = [mod3(word1 - word2) for word1 in code for word2 in code]
    for word in ncode:
        w = 0
        for i in word:
            if i != 0: w += 1

        if w != 0: weightList.append(w)

    return min(weightList)

#################
#   Exercise 1. #
#################
pprint('------- Exercise 1. -------')

n = 4
k = 2

# Basis vectors
x = array([1, 0, 1, 2])
y = array([0, 1, 1, 1])

# Generator matrix
G = array([ x, y ])

# The generated code
C = code(G)

pprint('The code C:')
pprint(C.tolist())

# 'The code C:'
# [[0, 0, 0, 0],
#  [1, 0, 1, 2],
#  [0, 1, 1, 1],
#  [2, 0, 2, 1],
#  [0, 2, 2, 2],
#  [1, 1, 2, 0],
#  [2, 1, 0, 2],
#  [1, 2, 0, 1]]

# Min Hamming distance
d = minD(C)

pprint('Min Hamming distance:')
pprint(d)

# 'Min Hamming distance:'
# 3

# Parity check matrix
h1 = mod3(array([-x[2], -y[2], 1, 0]))
h2 = mod3(array([-x[3], -y[3], 0, 1]))
H = array([ h1, h2 ])

pprint('Parity check matrix H:')
pprint(H)

# Test H
test([0, 1, 0, 1], H) # syndrome == [2, 0]

for v in C:
    test(v, H) # syndrome == [0, 0]

# Find if MDS
if d == n - k + 1: pprint('MDS') # This will be printed
else: pprint('Not MDS')

#################
#   Exercise 2. #
#################
pprint('------- Exercise 2. -------')

zeroVec = [0, 0, 0, 0]

BallWithDistanceOfOnefromZeroVector = [
    [1, 0, 0, 0],
    [0, 1, 0, 0],
    [0, 0, 1, 0],
    [0, 0, 0, 1],
    [2, 0, 0, 0],
    [0, 2, 0, 0],
    [0, 0, 2, 0],
    [0, 0, 0, 2],
]

for word in BallWithDistanceOfOnefromZeroVector:
    test(word, H)

incomingMessage = [2, 0, 0, 1]

def findCoset(syndrome):
    for word in BallWithDistanceOfOnefromZeroVector:
        cosetHeaderSyndrome = test(word, H, True)

        isCoset = True;
        for index, value in enumerate(cosetHeaderSyndrome):
            if value != syndrome[index]: isCoset = False

        if isCoset:
            pprint('Coset:')
            pprint(word)
            return word

incomingSyndrome = test(incomingMessage, H, True) # [1, 0]

coset = findCoset(incomingSyndrome)

correctWord = mod3(array(incomingMessage) - array(coset)).tolist()
pprint('Correct word:')
pprint(correctWord)

#################
#   Exercise 3. #
#################
pprint('------- Exercise 3. -------')

h1 = array([1, 1, 1, 0])
h2 = array([2, 0, 1, 1])

H = array([ h1, h2 ])

C = code(H)

N = array(
    [
        [0],
        [1],
        [2],
        [1],
    ]
).transpose()

pprint(mod3(matMul(H,N)))


# A python program that can generate the formula of a given sequence.
# Dependencies: SymPy

import sympy
from sympy.parsing.sympy_parser import parse_expr
import itertools as it
import math

class Sequence(object):
    '''A sequence object'''

    def __init__(self, sequence='1, 3, 5, 7, 217341'):
        try:
            self._seq = [float(i) for i in sequence.replace(' ','').split(',')]
        except ValueError:
            raise ValueError('invalid numbers')
        self._seqLen = len(self._seq)

    def _isArithmetic(self):
        '''When A_n = pn + q'''
        if len(self._seq) <= 2:
            if len(self._seq) == 1:
                return False, None
            elif len(self._seq) == 2:
                return True, self._seq[1] - self._seq[0]
        d = self._seq[1] - self._seq[0]
        if all([self._seq[i+1]-self._seq[i]==d for i in range(1, len(self._seq)-1)]):
            return True, d
        return False, None

    def _isGeometric(self):
        '''When A_n = p^(n-1) * q, or in special cases, A_n = p^(n+q)'''
        if len(self._seq) <= 2:
            if len(self._seq) == 1:
                return False, None
            elif len(self._seq) == 2:
                return True, self._seq[1] / self._seq[0]
        r = self._seq[1] / self._seq[0]
        if all([self._seq[i+1]/self._seq[i]==r for i in range(1, len(self._seq)-1)]):
            return True, r
        return False, None

    def generateFormula(self):
        '''Generates a formula for the sequence, returns a sympy object.\nMay not work for complex sequences.'''
        arithmetic, d = self._isArithmetic()
        if arithmetic:
            self.formula = sympy.nsimplify(parse_expr('{}*n + {}'.format(d, self._seq[0]-d)))
            return self.formula
        geometric, r = self._isGeometric()
        if geometric:
            log = math.log(self._seq[0], r)
            if log.is_integer():
                self.formula = sympy.nsimplify(parse_expr('{}**(n-1+{})'.format(r, log)))
            else:
                self.formula = sympy.nsimplify(parse_expr('{}**(n-1) * {}'.format(r, self._seq[0])))
            return self.formula
        else:
            tmp = []
            combinations = [i for i in it.combinations([l+1 for l in range(self._seqLen)], self._seqLen-1)]
            for combination, leftOut in zip(combinations, reversed([l+1 for l in range(self._seqLen)])):
                numerator = sympy.expand(parse_expr('*'.join(['(n-{})'.format(element) for element in combination])))
                denominator = parse_expr('*'.join(['({}-{})'.format(leftOut,element) for element in combination]))
                tmp.append(numerator / denominator)
            fractions = []
            for sequenceItem, element in zip(reversed(self._seq), tmp):
                fractions.append(sympy.nsimplify(sequenceItem) * element)
            self.formula = sympy.expand(sum(fractions))
            return self.formula

#Example Usage:
seq = Sequence(input('Input the sequence:'))
print('Formula:', end=' ')
print(seq.generateFormula())


import numpy as np
from chol_factor import chol_factor
from triangular import triangular

# TEST: Cholesky factorization (LL')

# Symmetric positive definite matrix
A = np.matrix('5    1.2  0.3 -0.6;'
              '1.2  6   -0.4  0.9;'
              '0.3 -0.4  8    1.7;'
             '-0.6  0.9  1.7  10');
print('A = \n', A)
# Computation of the L factor
L = chol_factor(A)
print('L = \n', L)
# Check
if np.allclose(A, np.dot(L, L.transpose())) == False:
    raise Exception('QR factorizzation test failure')

# TEST: System Resolution

# Ax = LL'x = b
b = np.matrix("68; 9; 45; 35")
print('b = \n', b)
# Lk = b
k = triangular(L, b, 1)
print('k = \n', k)
# L'x = k
x = triangular(L.transpose(), k, 0)
print('x = \n', x)
# Check
b1 = np.dot(A, x)
print('b1 = \n', b1)
if np.allclose(b, b1) == False:
    raise Exception('System resolution failure')


import math
import warnings

import numpy as np
import torch

from .geometry import cartesian_to_spherical

def rand_sphere(size):
    """
    Randomly sample on the sphere uniformly
    See http://corysimon.github.io/articles/uniformdistn-on-sphere/
    Our convention is 0 < theta < pi ; -pi < phi < pi
    :param size: torch.size or list of ints, size of returned tensors
    :return: theta, phi
    """
    theta = torch.acos(1 - 2 * torch.rand(size))
    phi = 2 * math.pi * torch.rand(size) - math.pi
    return theta, phi

def fibonacci_sphere(samples: int = 1000):
    """
    Evenly sample on the sphere
    See https://stackoverflow.com/questions/9600801/evenly-distributing-n-points-on-a-sphere
    :param samples: size of the array sampled
    :return : [samples, 3], torch.float, X, Y, and Z coordinates of the points in Euclidean space
    """
    increment = np.linspace(0, samples - 1, samples)
    phi = np.pi * (3. - np.sqrt(5.))  # golden angle in radians

    y = 1 - (increment / float(samples - 1)) * 2  # y goes from 1 to -1
    radius = np.sqrt(1 - y * y)  # radius at y

    theta = phi * increment  # golden angle increment

    x = np.cos(theta) * radius
    z = np.sin(theta) * radius

    return np.stack([x, y, z], axis=1)

def rejection_sphere_sampling(pdf, n: int = 1000, device=None, iter_max: int = 100):
    """
    Sample from a probability density function using rejection sampling
    See https://en.wikipedia.org/wiki/Rejection_sampling
    :param pdf: a function that takes as input a 1D vector theta and a 1D vector phi and return their densities
    :param n: number of samples
    :param device: torch.device
    :param iter_max: This algorithm can fail when the density function has big spikes,
        iter_max is the maximal number of iterations allowed
    :return: torch.float, [n, 2], theta and phi arrays
    """
    warnings.warn('rejection_sphere_sampling is a very basic loop, and can be very slow when the pdf function is' +
                  ' slow or has big spikes')
    if device is None:
        device = 'cpu'

    # Approximate upper bound value of the pdf
    xyz = torch.tensor(fibonacci_sphere(samples=5000), device=device)
    _, theta, phi = cartesian_to_spherical(xyz[:, 0], xyz[:, 1], xyz[:, 2])
    p_max = pdf(theta=theta, phi=phi).max()

    sample = torch.empty([0, 2], dtype=torch.float, device=device)
    n_iters = 0
    while sample.shape[0] < n:
        if n_iters > iter_max:
            raise RuntimeError('rejection_sphere_sampling did not succeed in time. Try to increase iter_max')
        # Rejection sampling
        y = torch.rand([2, n], device=device)  # Uniform distribution to create initial distribution
        theta = torch.acos(1 - 2 * y[0])
        phi = 2 * math.pi * y[1] - math.pi
        u = torch.rand([n], device=device)  # Uniform distribution to select valid and invalid samples

        valid = u < pdf(theta=theta, phi=phi) / p_max
        sample = torch.cat([sample,
                            torch.stack([theta[valid], phi[valid]], dim=1)],
                           dim=0)
        n_iters += 1

    sample = sample[:n]
    return sample


#neuro.py - a basic set of neural network functions
#these are almost entirely based on the functions
#provided in the textbook (Data Science from Scratch)
#This is not an efficient nor robust implementation.
#For educational purposes only.

from __future__ import division
import numpy as np
import math as math
import random
from linear_algebra import dot
import Image
import matplotlib.pyplot as mplot
import sys

weights=[]

def sigmoid(t):
    return 1 / (1 + math.exp(-t))

def neuron_output(weights, inputs):
    return sigmoid(dot(weights, inputs))

def predict(neural_network, input_vector):
    return feed_forward(neural_network, input_vector)[-1][0]

def feed_forward(neural_network, input_vector):
    """takes in a neural network
    (represented as a list of lists of lists of weights)
    and returns the output from forward-propagating the input"""
    outputs = []
    # process one layer at a time
    for layer in neural_network:
        input_with_bias = input_vector + [1] # add a bias input
        output = [neuron_output(neuron, input_with_bias) # compute the output
                  for neuron in layer] # for each neuron
        outputs.append(output) # and remember it
        # then the input to the next layer is the output of this one
        input_vector = output

    #print outputs
    return outputs

def backpropagate(network, input_vector, targets):
    output_layer=network[-1]
    hidden_outputs, outputs = feed_forward(network, input_vector)
    # the output * (1 - output) is from the derivative of sigmoid
    output_deltas = [output * (1 - output) * (output - target)
                     for output, target in zip(outputs, targets)]
    # adjust weights for output layer, one neuron at a time
    for i, output_neuron in enumerate(network[-1]):
        # focus on the ith output layer neuron
        for j, hidden_output in enumerate(hidden_outputs + [1]):
            # adjust the jth weight based on both
            # this neuron's delta and its jth input
            output_neuron[j] -= output_deltas[i] * hidden_output
    # back-propagate errors to hidden layer
    hidden_deltas = [hidden_output * (1 - hidden_output) *
                     dot(output_deltas, [n[i] for n in output_layer])
                     for i, hidden_output in enumerate(hidden_outputs)]
    # adjust weights for hidden layer, one neuron at a time
    for i, hidden_neuron in enumerate(network[0]):
        for j, input in enumerate(input_vector + [1]):
            hidden_neuron[j] -= hidden_deltas[i] * input

def train(network, input_vector, targets, reps):
    for __ in range(reps):
        for input, target in zip(input_vector,targets):
            backpropagate(network, input, target)

def setup_network(inputs):
    input_size = len(inputs[0])
    num_hidden = 5
    output_size = 1
    hidden_layer = [[random.randrange(-1, 1)*random.random() for __ in range(input_size + 1)]
                    for __ in range(num_hidden)]
    # each output neuron has one weight per hidden neuron, plus a bias weight
    output_layer = [[random.randrange(-1,1)*random.random() for __ in range(num_hidden + 1)]
                    for __ in range(output_size)]
# the network starts out with random weights
    network = [hidden_layer, output_layer]

    return network


import sympy as sp

x = sp.symbols("x")

y_exact = sp.exp(-x)

x1, x2 = sp.symbols("x1 x2")

# x1 = 0
# x2 = 1

y1 = sp.exp(-x1)
y2 = sp.exp(-x2)

y_approx = (y2 - y1)/(x2 - x1) * (x - x1) + y1
y_approx = sp.simplify(y_approx)

difference = y_approx - y_exact
difference = sp.simplify(difference)

L1error = sp.integrate(difference,(x,x1,x2))
L1error = sp.simplify(L1error)
# L2error = sp.integrate(difference**2,[x,x1,x2])


import math
import numpy as np
from numpy import *
from PIL import Image
from PIL import ImageDraw

# calculate derivative of Image in x and y directions
def derivative(arr):
    Ix = np.zeros((arr.shape[0], arr.shape[1]))
    Iy = np.zeros((arr.shape[0], arr.shape[1]))
    derivativeMask = np.array([-1,0,1])
    for i in range(1, arr.shape[0]-1):
        for j in range(1, arr.shape[1]-1):
            xtemp1 = arr[i, j - 1 : j + 2]
            xtemp2 = np.multiply(xtemp1, derivativeMask)
            ytemp1 = arr[i - 1 : i + 2, j]
            ytemp2 = np.multiply(ytemp1, derivativeMask.T)
            Ix[i, j] = xtemp2.sum()
            Iy[i, j] = ytemp2.sum()
    return Ix, Iy

# calculate eigen-value of the given matrix H1 and use it to find corners
def hessianCornerDetection(image):
    arr = np.array(image)
    lambda1 = np.zeros((arr.shape[0],arr.shape[1]))
    lambda2 = np.zeros((arr.shape[0],arr.shape[1]))
    Ix , Iy = derivative(arr)
    Ixx , Ixy = derivative(Ix)
    Iyx , Iyy = derivative(Iy)
    markArr = np.zeros((arr.shape[0],arr.shape[1]))
    count = 0
    for i in range(arr.shape[0]):
        for j in range(arr.shape[1]):
            temp = np.array( [ [ Ixx[i, j] , Iyx[i, j] ], [ Ixy[i, j], Iyy[i, j] ] ] )
            eigValue , eigVector = np.linalg.eig(temp)
            lambda1[i][j] = eigValue[0]
            lambda2[i][j] = eigValue[1]
            if lambda1[i,j] > 120 and lambda2[i,j] > 120:
                markArr[i,j] = 1
    return markArr

#  create a function to draw the corners which is detected by former algorithms
def drawCircleOnImg(Img, markArr):
    Img = Img.convert('RGB')
    draw = ImageDraw.Draw(Img)
    count = 0
    for i in range(markArr.shape[0]):
        for j in range(markArr.shape[1]):
            if markArr[i, j] > 0:
                draw.ellipse( (j - 2, i - 2, j + 2, i + 2), outline ='orange')
                count = count + 1
    print( "total circle drawing : " + str(count) )
    Img.show()

# main function to implement other functions
def main(imgPath):
    Img = Image.open(imgPath).convert('L')
    mark = hessianCornerDetection(Img)
    drawCircleOnImg(Img,mark)

main('input1.png')


import numpy as np
def trap(h, y1, y2):
	""" h is defined as (b-a) in which a and b are the limits of integration """
	return h * (y1+y2)/2

def trapm(h, y):
	""" h = (b-a)/(len(y)-1) where b and a are the limits of integration
		y  is an numpy compatability array
	"""
	n = len(y)-1
	sum = y[0] + y[-1]
	sum += np.sum(y[1:-1]) * 2
	return h * (sum/2)

def simp13(h, y1, y2, y3):
	""" h is defined as (b-a) in which a and b are the limits of integration """
	return (h) * (y1 + 4*y2 + y3)/6

def simp13m(h, y):
	""" h is defined as (b-a)/(len(y)-1) in which a and b are the limits of integration """
	sum = y[0] + y[-1]
	sum += np.sum(y[1:-1:2]) * 4
	sum += np.sum(y[2:-1:2]) * 2
	return sum * h / 3

def simp38(h, y1, y2, y3, y4):
	""" h is defined as (b-a) in which a and b are the limits of integration """
	return h * (y1 + 3*y2 + 3*y3 + y4)/8

print(trap(0.8, 0.2, 0.232))
#Data was taken as f(0), f(0.4), f(0.8); a = 0, b = 0.8, n = 2 or (3-1)
y = [0.2, 2.456, 0.232]
print(trapm(0.4, y))
print(simp13(0.8, *y))
#Data was taken as f(0), f(0.4), f(0.8); a = 0, b = 0.8, n = 2 or (3-1)
y2 = [0.2, 1.288, 2.456, 3.464, 0.232]
print(simp13m(0.8/4, y2))
y3 = [0.2, 1.432724, 3.487177, 0.232]
print(simp38(0.8, *y3))


import math
import matplotlib.patches
import matplotlib.pyplot
import numpy.random

from matplotlib.path import Path

def calculate_angle(source, point):
    x0, y0 = source
    x1, y1 = point
    dx = x1 - x0
    dy = y1 - y0
    angle = math.atan2(dy, dx)
    return (angle, point)

def calculate_angles(source, points):
    return [calculate_angle(source, point) for point in points]

def normalize_angle(theta, delta):
    if theta > delta:
        return theta - delta
    else:
        return theta - delta + math.pi * 2

def convexhull(points):
    """using the gift wrapping method"""
    start = max(points, key = lambda t : (t[1], t[0]))
    hull = [start] # start with the leftmost point
    while True:
        last = hull[-1]
        angles = calculate_angles(last, points)
        output = [angle for angle in angles if angle[1] not in hull] # list of (angle, points)
        if len(hull) == 1:
            next_point = min(output, key=lambda x: x[0])[1]
        else:
            second_last = hull[-2]
            output += [calculate_angle(last, hull[0])] # first hull point is always a candidate.
            delta = calculate_angle(second_last, last)[0]
            next_point = min(output, key=lambda x: normalize_angle(x[0], delta))[1]
        hull.append(next_point)
        if hull[-1] == hull[0]: break # terminal condition
    return hull

def generate_code(n):
    """generate path command codes for matplotlib for a convex hull"""
    result = []
    def index_to_code(i):
        if i == 0: return Path.MOVETO
        elif i == n - 1: return Path.CLOSEPOLY
        else: return Path.LINETO
    return map(index_to_code, xrange(n))

count = 0
fig = matplotlib.pyplot.figure()

def execute(points):
    global count
    global fig
    count += 1
    hull = convexhull(points)
    codes = generate_code(len(hull))
    path = Path(hull, codes)
    ax = fig.add_subplot(3, 2, count)
    limit = 10
    patch = matplotlib.patches.PathPatch(path, facecolor='orange', alpha = 0.1, lw=2)
    # plot the points
    x = [p[0] for p in points]
    y = [p[1] for p in points]
    ax.scatter(x, y, s = 10)
    # plot the convex hull
    ax.add_patch(patch)
    ax.set_xlim(-limit, limit)
    ax.set_ylim(-limit, limit)

def test_1():
    execute([(1, 0), (-1, 0), (0, 1), (0, -1), (0, 0)])

def test_2():
    execute([(1, 0), (-1, 0), (0, 1), (0, -1), (0, 0), (0, -0.25)])

def test_3():
    result = []
    for i in range(-2, 3):
        for j in range(-2, 3):
            # add a bit of variation
            result.append((i + numpy.random.normal(scale=0.01), j + numpy.random.normal(scale=0.01)))
    execute(result)

def test_random_1():
    result = []
    for i in range(100):
        result.append((numpy.random.normal(), numpy.random.normal()))
    execute(result)

def test_random_2():
    """two gaussian distributions"""
    result = []
    for i in range(1000):
        result.append((numpy.random.normal(2), numpy.random.normal(2)))
    for i in range(1000):
        result.append((numpy.random.normal(-2), numpy.random.normal(-2)))
    execute(result)

def test_random_3():
    """three gaussian distributions"""
    result = []
    for i in range(100):
        result.append((numpy.random.normal(3), numpy.random.normal()))
    for i in range(100):
        result.append((numpy.random.normal(-3), numpy.random.normal()))
    for i in range(100):
        result.append((numpy.random.normal(), numpy.random.normal(-3)))
    execute(result)

test_random_1()
test_random_2()
test_random_3()
test_1()
test_2()
test_3()
matplotlib.pyplot.show()


"""Spearman's Rank Correlation Coefficient"""
import typing
import numpy as np
import scipy
from h2oaicore.metrics import CustomScorer

class Spearman_Correlation(CustomScorer):
    _description = "Spearman's Rank Correlation Coefficient"
    _regression = True
    _maximize = True
    _perfect_score = 1.
    _supports_sample_weight = False
    _display_name = "SpearmanR"

    def score(self,
              actual: np.array,
              predicted: np.array,
              sample_weight: typing.Optional[np.array] = None,
              labels: typing.Optional[np.array] = None) -> float:
        if sample_weight is None:
            sample_weight = np.ones(actual.shape[0])

        # Spearman's Rank Correlation
        return scipy.stats.spearmanr(actual, predicted)[0]


# -*- coding: utf-8 -*-
import numpy as np
import pandas as pd

def fractal_katz(signal):

    """**Katz's Fractal Dimension (KFD)**

    Computes Katz's Fractal Dimension (KFD). The euclidean distances between successive points in
    the signal are summed and averaged, and the maximum distance between the starting point and any
    other point in the sample.

    Here, fractal dimensions range from 1.0 for straight lines, through
    approximately 1.15 for random-walk waveforms, to approaching 1.5 for the most
    convoluted waveforms.

    Parameters
    ----------
    signal : Union[list, np.array, pd.Series]
        The signal (i.e., a time series) in the form of a vector of values.

    Returns
    -------
    kfd : float
        Katz's fractal dimension of the single time series.
    info : dict
        A dictionary containing additional information (currently empty, but returned nonetheless
        for consistency with other functions).

    Examples
    ----------
    * **Step 1.** Simulate different kinds of signals

    .. ipython:: python

      import neurokit2 as nk
      import numpy as np

      # Simulate straight line
      straight = np.linspace(-1, 1, 2000)

      # Simulate random
      random = nk.complexity_simulate(duration=2, method="randomwalk")
      random = nk.rescale(random, [-1, 1])

      # Simulate simple
      simple = nk.signal_simulate(duration=2, frequency=[5, 10])

      # Simulate complex
      complex = nk.signal_simulate(duration=2,
                                   frequency=[1, 3, 6, 12],
                                   noise = 0.1)

      @savefig p_katz.png scale=100%
      nk.signal_plot([straight, random, simple, complex])

    * **Step 2.** Compute KFD for each of them

    .. ipython:: python

      KFD, _ = nk.fractal_katz(straight)
      KFD
      KFD, _ = nk.fractal_katz(random)
      KFD
      KFD, _ = nk.fractal_katz(simple)
      KFD
      KFD, _ = nk.fractal_katz(complex)
      KFD

    References
    ----------
    * Katz, M. J. (1988). Fractals and the analysis of waveforms.
      Computers in Biology and Medicine, 18(3), 145-156. doi:10.1016/0010-4825(88)90041-8.

    """

    # Sanity checks
    if isinstance(signal, (np.ndarray, pd.DataFrame)) and signal.ndim > 1:
        raise ValueError(
            "Multidimensional inputs (e.g., matrices or multichannel data) are not supported yet."
        )

    # Force to array
    signal = np.array(signal)

    # Drop missing values
    signal = signal[~np.isnan(signal)]

    # Define total length of curve
    dists = np.abs(np.diff(signal))
    length = np.sum(dists)

    # Average distance between successive points
    a = np.mean(dists)

    # Compute farthest distance between starting point and any other point
    d = np.max(np.abs(signal - signal[0]))

    kfd = np.log10(length / a) / (np.log10(d / a))

    return kfd, {}