import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.datasets import make_moons
from matplotlib.colors import ListedColormap
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import validation_curve

show_charts = False
save_path = '/Users/gustavoamarante/Dropbox/Aulas/QuantFin/figures/'

k_test = 51
h = 0.02  # step size in the mesh

# ===== GENERATE DATA =====
X, y = make_moons(noise=0.3,
                  random_state=444,
                  n_samples=200)

# plot the data
cmap_light = ListedColormap(['#FFBC00', '#5FC4FF'])
cmap_bold = ['#FF570A', '#2F34AF']

plt.figure(figsize=(6, 6))
ax = plt.gca()
ax.scatter(X[:, 0], X[:, 1], c=y, cmap=ListedColormap(cmap_bold), edgecolor="black", label=None)
ax.set(xlabel='$X$', ylabel='$Y$')
plt.tight_layout()
plt.savefig(save_path + 'KNN - simulated data.pdf')

if show_charts:
    plt.show()

plt.close()

# ===== DECISION REGION FOR K=1 ======
clf = KNeighborsClassifier(n_neighbors=1)
clf.fit(X, y)

x_min, x_max = X[:, 0].min() - 0.5, X[:, 0].max() + 0.5
y_min, y_max = X[:, 1].min() - 0.5, X[:, 1].max() + 0.5
xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))
Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)

# Put the result into a color plot
plt.figure(figsize=(6, 6))
plt.contourf(xx, yy, Z, cmap=cmap_light, alpha=0.6)

# Plot also the training points
sns.scatterplot(x=X[:, 0], y=X[:, 1], hue=y, alpha=1, edgecolor="black", palette=cmap_bold, legend=None)
plt.xlim(xx.min(), xx.max())
plt.ylim(yy.min(), yy.max())
ax = plt.gca()
ax.set(xlabel='$X$', ylabel='$Y$',
       title='Classification with $K=1$')
plt.tight_layout()
plt.savefig(save_path + 'KNN - classification k=1.pdf')

if show_charts:
    plt.show()

plt.close()

# ===== CROSS VALIDATION FOR K =====
train_scores, valid_scores = validation_curve(estimator=KNeighborsClassifier(), X=X, y=y, cv=2,
                                              param_name='n_neighbors', param_range=range(1, k_test),
                                              verbose=1)

train_score = train_scores.mean(axis=1)
test_score = valid_scores.mean(axis=1)

df = pd.DataFrame(data={'Train Score': train_score,
                        'Test Score': test_score},
                  index=range(1, k_test))

K = df['Test Score'].idxmax()
print(K)

df.plot()
ax = plt.gca()
ax.set(xlabel='$K$ Nearest Neighbours', ylabel='% Correct Classifications')
ax.yaxis.grid(color='grey', linestyle='-', linewidth=0.5, alpha=0.5)
plt.tight_layout()
plt.savefig(save_path + 'KNN - Cross validation.pdf')

if show_charts:
    plt.show()

plt.close()

# ===== DECISION REGION FOR K=OPTIMAL ======
clf = KNeighborsClassifier(n_neighbors=K)
clf.fit(X, y)

x_min, x_max = X[:, 0].min() - 0.5, X[:, 0].max() + 0.5
y_min, y_max = X[:, 1].min() - 0.5, X[:, 1].max() + 0.5
xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))
Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)

# Put the result into a color plot
plt.figure(figsize=(6, 6))
plt.contourf(xx, yy, Z, cmap=cmap_light, alpha=0.6)

# Plot also the training points
sns.scatterplot(x=X[:, 0], y=X[:, 1], hue=y, alpha=1, edgecolor="black", palette=cmap_bold, legend=None)
plt.xlim(xx.min(), xx.max())
plt.ylim(yy.min(), yy.max())

ax = plt.gca()
ax.set(xlabel='$X$', ylabel='$Y$',
       title=f'Classification with $K={K}$')
plt.tight_layout()
plt.savefig(save_path + 'KNN - classification k=optimal.pdf')

if show_charts:
    plt.show()

plt.close()

# ===== DECISION REGION FOR K=50 ======
clf = KNeighborsClassifier(n_neighbors=50)
clf.fit(X, y)

x_min, x_max = X[:, 0].min() - 0.5, X[:, 0].max() + 0.5
y_min, y_max = X[:, 1].min() - 0.5, X[:, 1].max() + 0.5
xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))
Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)

# Put the result into a color plot
plt.figure(figsize=(6, 6))
plt.contourf(xx, yy, Z, cmap=cmap_light, alpha=0.6)

# Plot also the training points
sns.scatterplot(x=X[:, 0], y=X[:, 1], hue=y, alpha=1, edgecolor="black", palette=cmap_bold, legend=None)
plt.xlim(xx.min(), xx.max())
plt.ylim(yy.min(), yy.max())

ax = plt.gca()
ax.set(xlabel='$X$', ylabel='$Y$',
       title=f'Classification with $K=50$')
plt.tight_layout()
plt.savefig(save_path + 'KNN - classification k=50.pdf')

if show_charts:
    plt.show()

plt.close()


import numpy as np

def normPDF(x, mean, sigma):
    return exp(-1.*(x-mean)**2/(2.*sigma**2))
    # return (1/np.sqrt(2.*np.pi*sigma**2))*exp(-1.*(x-mean)**2/(2.*sigma**2))

def normSigma(x, mean, probability):
    return np.sqrt(-0.5*(x-mean)**2/np.log(probability))

def normInverse(p, mu, sigma):
    """
    return the offset to the Gaussian center given the Gaussian informaton

    Keyword arguments:
    p -- the Gaussian probabilty
    mu -- the center of the Gaussian
    sigma -- the deviation  of the Gaussian

    return:
    offset -- the offset to the Gaussian center given the parameters

    """

    x = np.sqrt(-2.*sigma**2.*np.log(p))+mu
    return x


import matplotlib.pyplot as plt
import numpy as np

u = np.linspace(-3, 3, 25)
v = np.linspace(-3, 3, 25)
uu, vv = np.meshgrid(u, v)
z = uu + 1j * vv
# w = 1/z
# w = np.exp(z)
# w = np.log(z)
w = np.sin(z)
T = np.arctan2(uu, vv)

fig = plt.figure()
ax = fig.add_subplot(111)
color = 2 * np.log(np.hypot(np.real(w), np.imag(w)))
# ax.streamplot(np.real(z), np.imag(z), np.real(w), np.imag(w), color=color, linewidth=1, cmap=plt.cm.inferno,
#               density=2, arrowstyle='->', arrowsize=1.5)

Q = plt.quiver(np.real(z), np.imag(z), np.real(w), np.imag(w), units='width')
qk = plt.quiverkey(Q, 0.9, 0.9, 2, r'$2 \frac{m}{s}$', labelpos='E',
                   coordinates='figure')

ax.set_xlabel('$x$')
ax.set_ylabel('$y$')
# ax.set_xlim(-2, 2)
# ax.set_ylim(-2, 2)
ax.set_aspect('equal')
# plt.title('f(z)=1/z')
# plt.title('f(z)=exp(z)')
# plt.title('f(z)=log(z)')
plt.title('f(z)=sin(z)')
plt.show()


import math
import copy
import numpy as np

class Complex:

    # No initialization is needed as this is merely a class of functions, as Python already has a fairly robust
    # complex number library that was well worth using, as its basis is in one of the c languages

    # Returns the norm (magnitude) of the complex number - tested in complex_norms_test.py
    @staticmethod
    def norm(c=complex):
        return math.sqrt((c.real ** 2 + c.imag ** 2))

    # Returns the normed (unit) version of the compelx number - tested in complex_norms_test.py
    @staticmethod
    def normed(c=complex):
        norm = Complex.norm(c)
        return complex(c.real / norm, c.imag / norm)

    # Returns the same complex number but with the imaginary component negated - tested in complex_conjugate_test.py
    @staticmethod
    def conjugate(c=complex):
        return complex(c.real, c.imag * -1)

# Two Dimensional Vectors - the mentioned R2 coordinate space.

class Vector2:

    def __init__(self, a, b):
        self.a = a  # value along x axis
        self.b = b  # value alogn y axis

    # Multiplies the vector by a scalar - evaluated in vector2_scale_test.py
    def scale(self, scalar):
        return Vector2(self.a * scalar, self.b * scalar)

    # Returns the norm (magnitude) of the vector - tested in vector2_norms_test.py
    @property
    def norm(self):
        return math.sqrt((self.a ** 2 + self.b ** 2))

    # Returns the normed (unit) version of the vector - tested in vector2_norms_test.py
    @property
    def normed(self):
        norm = self.norm
        return Vector2(self.a / norm, self.b / norm)

    # Prints the vector in <i, j> form
    @property
    def string(self):
        return f'<{self.a}, {self.b}>'

    # Returns the sum of n vectors - tested in vector2_sum_difference_test.py
    @classmethod
    def sum(cls, *args):
        v = copy.copy(args[0])

        for j in args[1:]:
            a = v.a + j.a
            b = v.b + j.b
            v.a, v.b = a, b  # Not too sure why this final line is needed; answer was incorrect otherwise
        return v

    # Returns the difference of n vectors - tested in vector2_sum_difference_test.py
    @classmethod
    def difference(cls, *args):
        v = copy.copy(args[0])

        for j in args[1:]:
            a = v.a - j.a
            b = v.b - j.b
            v.a, v.b = a, b  # Not too sure why this final line is needed; answer was incorrect otherwise
        return v

    # Returns the dot product of two vectors - tested in vector2_dot_test.py
    @classmethod
    def dot_product(cls, v1, v2):
        return v1.a * v2.a + v1.b * v2.b

    # This function determines the angle between two vectors using the dot product of the normed inputs and acos. Output
    # is in radians. - tested in vector2_angle_test.py
    @classmethod
    def angle(cls, v1, v2):
        v1 = v1.normed
        v2 = v2.normed
        dot = cls.dot_product(v1, v2)
        return math.acos(dot)

# Three Dimensional Vectors - the mentioned R3 coordinate space.

class Vector3:

    # Initialization

    def __init__(self, a, b, c):
        self.a = a  # value along x axis
        self.b = b  # value along y axis
        self.c = c  # value along z axis

    # Multiplies the vector by a scalar - evaluated in vector3_scale_test.py
    def scale(self, scalar):
        return Vector3(self.a * scalar, self.b * scalar, self.c * scalar)

    # Properties

    # Returns the norm (magnitude) of the vector - tested in vector3_norms_test.py
    @property
    def norm(self):
        return math.sqrt((self.a ** 2 + self.b ** 2 + self.c ** 2))

    # Returns the normed (unit) version of the vector - tested in vector3_norms_test.py
    @property
    def normed(self):
        return self.scale(scalar=(1 / self.norm))

    # Prints the vector in <i, j, k> form
    @property
    def string(self):
        return f'<{self.a}, {self.b}, {self.c}>'

    # Class Methods

    # Returns the sum of n vectors - tested in vector3_sum_difference_test.py
    @classmethod
    def sum(cls, *args):
        v = copy.copy(args[0])

        for j in args[1:]:
            a = v.a + j.a
            b = v.b + j.b
            c = v.c + j.c
            v.a, v.b, v.c = a, b, c  # Not too sure why this final line is needed; answer was incorrect otherwise
        return v

    # Returns the difference of n vectors - tested in vector3_sum_difference_test.py
    @classmethod
    def difference(cls, *args):
        v = copy.copy(args[0])

        for j in args[1:]:
            a = v.a - j.a
            b = v.b - j.b
            c = v.c - j.c
            v.a, v.b, v.c = a, b, c  # Not too sure why this final line is needed; answer was incorrect otherwise
        return v

    # Returns the vector orthogonal to both input vectors - tested in vector3_cross_test.py
    @classmethod
    def cross_product(cls, v1, v2):
        v3a = v1.b * v2.c - v1.c * v2.b
        v3b = v1.c * v2.a - v1.a * v2.c
        v3c = v1.a * v2.b - v1.b * v2.a
        return Vector3(v3a, v3b, v3c)

    # Returns the dot product of two vectors - tested in vector3_dot_test.py
    @classmethod
    def dot_product(cls, v1, v2):
        return v1.a * v2.a + v1.b * v2.b + v1.c * v2.c

    # This function determines the angle between two vectors using the dot product of the normed inputs and acos. Output
    # is in radians - evaluated in vector3_angle_test.py
    @classmethod
    def angle(cls, v1, v2):
        v1 = v1.normed
        v2 = v2.normed
        dot = cls.dot_product(v1, v2)
        return math.acos(dot)

# Quaternions

class Quaternion:

    # Initialization

    def __init__(self, a, b, c, d):
        self.a = a  # the scalar component
        self.b = b  # quaternionic i component
        self.c = c  # quaternionic j component
        self.d = d  # quaternionic k component

    # Returns a scaled version of the quaternion, where every element has been multiplied by some scalar variable
    # - tested in quaternion_scale_test.py
    def scale(self, scalar):
        return Quaternion(self.a * scalar, self.b * scalar, self.c * scalar, self.d * scalar)

    # Properties

    # Return the quaternion equivalent of a complex conjugate - tested in quaternion_pure_and_rotations_test.py
    @property
    def conjugate(self):
        return Quaternion(self.a, -1 * self.b, -1 * self.c, -1 * self.d)

    # Return the magnitude of a quaternion
    @property
    def norm(self) -> float:
        return math.sqrt((self.a ** 2 + self.b ** 2 + self.c ** 2 + self.d ** 2))

    # Return the a quaternion with magnitude 1, thus an element of SU(2) and member of SO(3) - tested in quaternion_pure_and_rotations_test.py
    @property
    def normed(self):
        return self.scale(scalar=(1 / self.norm))

    # Class Methods

    # Sums n quaternions
    @classmethod
    def sum(cls, *args):
        q = copy.copy(args[0])

        for j in args[1:]:
            a = q.a + j.a
            b = q.b + j.b
            c = q.c + j.c
            d = q.d + j.d
            q.a, q.b, q.c, q.d = a, b, c, d  # Not too sure why this final line is needed; answer was incorrect otherwise
        return q

    # Returns the difference of n quaternions
    @classmethod
    def difference(cls, *args):
        q = copy.copy(args[0])

        for j in args[1:]:
            a = q.a - j.a
            b = q.b - j.b
            c = q.c - j.c
            d = q.d - j.d
            q.a, q.b, q.c, q.d = a, b, c, d  # Not too sure why this final line is needed; answer was incorrect otherwise
        return q

    # Returns the quaternionic product of n quaternions - tested in quaternion_pure_and_rotations_test.py
    @classmethod
    def product(cls, *args):
        q = copy.copy(args[0])

        for j in args[1:]:
            a = (q.a * j.a) - (q.b * j.b) - (q.c * j.c) - (q.d * j.d)
            b = (q.a * j.b) + (q.b * j.a) + (q.c * j.d) - (q.d * j.c)
            c = (q.a * j.c) - (q.b * j.d) + (q.c * j.a) + (q.d * j.b)
            d = (q.a * j.d) + (q.b * j.c) - (q.c * j.b) + (q.d * j.a)
            q.a, q.b, q.c, q.d = a, b, c, d  # Not too sure why this final line is needed; answer was incorrect otherwise
        return q

    # Return a quaternion form of a vector in R3 - tested in quaternion_pure_and_rotations_test.py
    @classmethod
    def pure_qt(cls, vector=Vector3):
        return Quaternion(0, vector.a, vector.b, vector.c)

    # Rotates a point using a quaternion - tested in quaternion_pure_and_rotations_test.py
    @classmethod
    def rotate(cls, q, p=Vector3):
        if q.norm < 1.00000001 and q.norm > 0.99999999:  # manual control over float error
            qd = q.conjugate
            p = cls.pure_qt(p)
            qpqd = cls.product(q, p, qd)
            return Vector3(qpqd.b, qpqd.c, qpqd.d)
        else:
            raise ArithmeticError

    # Generates a rotation about an axis; based off the syntax from point_rotation, which was tested in quaternion_pure_and_rotations_test.py
    @classmethod
    def axis_rotation(cls, angle=float, axis=Vector3):
        angle *= 0.5
        axis = axis.normed
        axis = axis.scale(math.sin(angle))
        q = Quaternion(math.cos(angle), axis.a, axis.b, axis.c)
        return q

    # Generates the rotation quaternion that will rotate point p1 to point p2
    @classmethod
    def point_rotation(cls, p1=Vector3, p2=Vector3):
        angle = Vector3.angle(p1, p2) * 0.5
        axis = Vector3.cross_product(p1, p2).normed
        axis = axis.scale(math.sin(angle))
        q = Quaternion(math.cos(angle), axis.a, axis.b, axis.c)
        return q

# Complex Quaternions

class QtComplex:

    # Initialization

    def __init__(self, c1, c2, c3, c4):
        self.c1 = c1  # first complex element
        self.c2 = c2  # second complex element
        self.c3 = c3  # third complex element
        self.c4 = c4  # fourth complex element

    # Returns the complex linear combination (CLC) notation for the complex quaternion
    @property
    def CLC(self):
        string = f'{self.c1, self.c2, self.c3, self.c4}'
        return string

    # Returns the real linear combination (RLC) notation for the complex quaternion
    @property
    def RLC(self):
        string = f'{self.c1.real, self.c1.imag, self.c2.real, self.c3.real, self.c4.real, self.c2.imag, self.c3.imag, self.c4.imag}'
        return string

    # Returns a complex quaternion whose quaternionic elements are negated; in CLC, these are the last three elements,
    # in RLC it is the last six
    @property
    def quaternion_conjugate(self):
        return QtComplex(self.c1, self.c2 * -1, self.c3 * -1, self.c4 * -1)

    # Returns a complex quaternion whose complex i values are negated; this is the imaginary component of each element
    # in CLC notation, and the 2nd - 5th element in RLC notation
    @property
    def complex_conjugate(self):
        c1 = Complex.conjugate(self.c1)
        c2 = Complex.conjugate(self.c2)
        c3 = Complex.conjugate(self.c3)
        c4 = Complex.conjugate(self.c4)
        return QtComplex(c1, c2, c3, c4)

    # Returns the both the complex and quaternionic conjugate in one complex quaternion
    @property
    def hermitian_conjugate(self):
        c1 = Complex.conjugate(self.c1)
        c2 = Complex.conjugate(self.c2) * -1
        c3 = Complex.conjugate(self.c3) * -1
        c4 = Complex.conjugate(self.c4) * -1
        return QtComplex(c1, c2, c3, c4)

    # Class Methods

    # Allows definition of a complex quaternion through a real linear combination
    @classmethod
    def real_linear(cls, a, b, i, j, k, ii, ij, ik):
        c1 = complex(a, b)
        c2 = complex(i, ii)
        c3 = complex(j, ij)
        c4 = complex(k, ik)
        return QtComplex(c1, c2, c3, c4)

    # The complex quaternion multiplicative product
    @classmethod
    def product(cls, *args):
        cq = copy.copy(args[0])

        for j in args[1:]:
            c1 = (cq.c1 * j.c1) - (cq.c2 * j.c2) - (cq.c3 * j.c3) - (cq.c4 * j.c4)
            c2 = (cq.c1 * j.c2) + (cq.c2 * j.c1) + (cq.c3 * j.c4) - (cq.c4 * j.c3)
            c3 = (cq.c1 * j.c3) - (cq.c2 * j.c4) + (cq.c3 * j.c1) + (cq.c4 * j.c2)
            c4 = (cq.c1 * j.c4) + (cq.c2 * j.c3) - (cq.c3 * j.c2) + (cq.c4 * j.c1)
            cq.c1, cq.c2, cq.c3, cq.c4 = c1, c2, c3, c4

        return cq

class DualQuaternion:
    def __init__(self, a, b, c, d, e, ei, ej, ek):
        self.a = a
        self.b = b
        self.c = c
        self.d = d
        self.e = e
        self.ei = ei
        self.ej = ej
        self.ek = ek

    @property
    def ELC(self):
        string = f'{self.a, self.b, self.c, self.d, self.e, self.ei, self.ej, self.ek}'
        return string

    @property
    def QTA(self):
        string = f'{self.a, self.b, self.c, self.d}'
        return

    @property
    def QTB(self):
        string = f'{self.e, self.ei, self.ej, self.ek}'
        return

    @property
    def dualQuaternionConjugate(self):
        a = self.a
        b = -1 * self.b
        c = -1 * self.c
        d = -1 * self.d
        e = self.e
        ei = -1 * self.ei
        ej = -1 * self.ej
        ek = -1 * self.ek
        return DualQuaternion(a, b, c, d, e, ei, ej, ek)

    @property
    def dualNumberConjugate(self):
        a = self.a
        b = self.b
        c = self.c
        d = self.d
        e = -1 * self.e
        ei = -1 * self.ei
        ej = -1 * self.ej
        ek = -1 * self.ek
        return DualQuaternion(a, b, c, d, e, ei, ej, ek)

    @property
    def fullConjugate(self):
        a = self.a
        b = -1 * self.b
        c = -1 * self.c
        d = -1 * self.d
        e = -1 * self.e
        ei = self.ei
        ej = self.ej
        ek = self.ek
        return DualQuaternion(a, b, c, d, e, ei, ej, ek)

    # Sums n dual quaternions
    @classmethod
    def sum(cls, *args):
        q = copy.copy(args[0])

        for j in args[1:]:
            a = q.a + j.a
            b = q.b + j.b
            c = q.c + j.c
            d = q.d + j.d
            e = q.e + j.e
            ei = q.ei + j.ei
            ej = q.ej + j.ej
            ek = q.ek + j.ek
            q.a, q.b, q.c, q.d, q.e, q.ei, q.ej, q.ek = a, b, c, d, e, ei, ej, ek
        return q

    # Returns the difference of n dual quaternions
    @classmethod
    def difference(cls, *args):
        q = copy.copy(args[0])

        for j in args[1:]:
            a = q.a - j.a
            b = q.b - j.b
            c = q.c - j.c
            d = q.d - j.d
            e = q.e - j.e
            ei = q.ei - j.ei
            ej = q.ej - j.ej
            ek = q.ek - j.ek
            q.a, q.b, q.c, q.d, q.e, q.ei, q.ej, q.ek = a, b, c, d, e, ei, ej, ek
        return q

    @classmethod
    def product(cls, *args):
        q = copy.copy(args[0])

        for j in args[1:]:

            # elements of first quaternion in dual quaternion product

            a = (q.a * j.a) - (q.b * j.b) - (q.c * j.c) - (q.d * j.d)
            b = (q.a * j.b) + (q.b * j.a) + (q.c * j.d) - (q.d * j.c)
            c = (q.a * j.c) - (q.b * j.d) + (q.c * j.a) + (q.d * j.b)
            d = (q.a * j.d) + (q.b * j.c) - (q.c * j.b) + (q.d * j.a)

            # elements of the second quaternion in dual quaternion product

            e = ((q.a * j.e) - (q.b * j.ei) - (q.c * j.ej) - (q.d * j.ek)) + ((q.e * j.a) - (q.ei * j.b) - (q.ej * j.c) - (q.ek * j.d))
            ei = ((q.a * j.ei) + (q.b * j.e) + (q.c * j.ek) - (q.d * j.ej)) + ((q.e * j.b) + (q.ei * j.a) + (q.ej * j.d) - (q.ek * j.c))
            ej = ((q.a * j.ej) - (q.b * j.ek) + (q.c * j.e) + (q.d * j.ei)) + ((q.e * j.c) - (q.ei * j.d) + (q.ej * j.a) + (q.ek * j.b))
            ek = ((q.a * j.ek) + (q.b * j.ej) - (q.c * j.ei) + (q.d * j.e)) + ((q.e * j.d) + (q.ei * j.c) - (q.ej * j.b) + (q.ek * j.a))

            # redefine q values to new calculated ones

            q.a, q.b, q.c, q.d, q.e, q.ei, q.ej, q.ek = a, b, c, d, e, ei, ej, ek

        return q


##### LINEAR REGRESSION - PSEUDOINVERSION #####

import numpy as np
import matplotlib.pyplot as plt
from scipy import stats             # for verification
from sklearn import linear_model    # for verification
from sklearn.metrics import mean_squared_error, r2_score

data = np.loadtxt('data.txt')       # shape (50, 2)

x = data[:, 0]      # shape (50,)
y = data[:, 1]      # shape (50,)

plt.figure(1, figsize=(10, 8), dpi=100, facecolor='w', edgecolor='k')
plt.scatter(x, y, color='purple', label='original data')

### Pseudoinversion method

print("Pseudoinversion method")

X = np.ones((data.shape[0], 1))
X = np.concatenate((X, x[:, np.newaxis]), axis=1)

theta_optimal = np.dot(np.dot(np.linalg.inv(np.dot(X.T, X)), X.T), y)       # shape (2,)

y_hat = theta_optimal[0] + theta_optimal[1] * x

plt.plot(x, y_hat, 'g-', linewidth=7.0, label = 'pseudoinv fitted line')

print("theta_optimal:", theta_optimal)      # [-10.61262592, 6.90359569]
print("R-squared:", r2_score(y, y_hat))     # 0.96

### Verification

# Scipy
print("\nScipy")
slope, intercept, r_value, p_value, std_err = stats.linregress(x, y)
print("intercept, slope:", intercept, slope)
#print(np.allclose(theta_optimal, [intercept, slope]))
y_pred = intercept + slope * x
plt.plot(x, y_pred, color='red', linewidth=3.0, label = 'scipy fitted line')
print("R-squared:", r_value**2)             # 0.96
print("R-squared:", r2_score(y, y_pred))    # 0.96

# scikit-learn Linear Regression
print("\nscikit-learn Linear Regression")
reg = linear_model.LinearRegression()
reg.fit(x.reshape(-1, 1), y)
y_pred = reg.predict(x.reshape(-1, 1))
plt.plot(x, y_pred, color='black', linestyle='-', linewidth=1.0, label = 'scikit LR fitted line')
print("intercept, slope:", reg.intercept_, reg.coef_)
print("R-squared:", r2_score(y, y_pred))    # 0.96

# scikit-learn Ridge
print("\nscikit-learn Ridge")
clf = linear_model.Ridge()
clf.fit(x[:, np.newaxis], y)
y_pred = clf.predict(x[:, np.newaxis])
plt.plot(x, y_pred, color='orange', linestyle='', marker='2', label = 'scikit Ridge fitted line')
print("intercept, slope:", clf.intercept_, clf.coef_)
print("R-squared:", r2_score(y, y_pred))    # 0.96

plt.xlabel('data')
plt.ylabel('target')
plt.legend()

plt.figure(2, figsize=(10, 8), dpi=100, facecolor='w', edgecolor='k')
plt.scatter(x, y, color='purple', label='original data')
plt.plot(x, y_hat, 'k-', linewidth=2.0, label = 'pseudoinv fitted line')

# SGD works better with features centered around zero, with standard deviation of 1.
mean, std = x.mean(), x.std()
x_scaled = (x - mean) / std

# scikit-learn SGDRegressor
print("\nscikit-learn SGDRegressor")
clf = linear_model.SGDRegressor(loss="squared_loss", penalty="l2", max_iter=1000, tol=1e-3, shuffle=True)
clf.fit(x_scaled[:, np.newaxis], y)
y_pred = clf.predict(x_scaled[:, np.newaxis])
plt.plot(x, y_pred, color='yellow', linestyle='-', linewidth=1.0, label = 'scikit SGDRegressor fitted line')
print("intercept, slope:", clf.intercept_, clf.coef_)
print("R-squared:", r2_score(y, y_pred))    # 0.96

plt.xlabel('data')
plt.ylabel('target')
plt.legend()

plt.show()


import numpy as N
from math import *

class MCOptionPricer(object):
    def __init__(self, S=100.0, K=100.0, sigma=0.25, r=0.05, days=260, paths=10000):
        self.S = S
        self.K = K
        self.sigma = sigma
        self.r = r
        self.days = days
        self.paths = paths
        self.h = 1.0/self.days
        self.const1 = exp((self.r-0.5*self.sigma**2)*self.h)
        self.const2 = self.sigma*sqrt(self.h)

    def run(self):
        stock_price = self.S*N.ones(self.paths, dtype='float64')
        stock_price_sum = N.zeros(self.paths, dtype='float64')
        for j in range(self.days):
            growth_factor = self.const1*N.exp(self.const2*N.random.standard_normal(self.paths))
            stock_price = stock_price*growth_factor
            stock_price_sum = stock_price_sum + stock_price
        stock_price_avg = stock_price_sum/self.days
        zeros = N.zeros(self.paths, dtype='float64')
        r_factor = exp(-self.r*self.h*self.days)
        self.vanilla_put = r_factor*N.mean(N.maximum(zeros,self.K-stock_price))
        self.asian_put = r_factor*N.mean(N.maximum(zeros,self.K-stock_price_avg))
        self.vanilla_call = r_factor*N.mean(N.maximum(zeros,stock_price-self.K))
        self.asian_call = r_factor*N.mean(N.maximum(zeros,stock_price_avg-self.K))

def main():
    op = MCOptionPricer()
    op.run()
    print "Vanilla Put Price = ", op.vanilla_put
    print "Asian Put Price = ", op.asian_put
    print "Vanilla Call Price = ", op.vanilla_call
    print "Asian Call Price = ", op.asian_call

if __name__ == '__main__':
    main()


# by Huaiyu TAN

import numpy as np
def is_dd(M: list):
    p = 0
    for i in range(len(M)):
        if np.sum(np.abs(M[i]))-np.abs(M[i][i]) >= np.abs(M[i][i]):
            p += 1
    if p == 0:
        print("The Matrix is diagonally dominant !")
    else:
        print("The Matrix is not diagonally dominant !")
    return p

M = np.array([[3,2,0],[-4,-20,-6],[7,1,9]])
p = is_dd(M)


import matplotlib.pyplot as plt
from skimage import io
from skimage import img_as_float
import numpy as np
import numpy.matlib
import math

file_name='tripod.png';
img=io.imread(file_name)

img = img_as_float(img)

row, col, channel = img.shape

# set the parameters
radius = 100.0
angle = math.pi/3
angle2 = math.pi/4
sides = 10.0
# set the center of the circle, proportion of the image size
centerX = 0.5
centerY = 0.5

iWidth=col
iHeight=row

center_x=iWidth*centerX
center_y=iHeight*centerY

xx = np.arange (col)
yy = np.arange (row)

x_mask = numpy.matlib.repmat (xx, row, 1)
y_mask = numpy.matlib.repmat (yy, col, 1)
y_mask = np.transpose(y_mask)

xx_dif = x_mask - center_x
yy_dif = y_mask - center_y

r = np.sqrt(xx_dif * xx_dif + yy_dif * yy_dif)
theta = np.arctan2(yy_dif, xx_dif+0.0001) - angle - angle2
temp_theta=theta/math.pi*sides*0.5
temp_r = np.mod(temp_theta, 1.0)
mask_1 = temp_r < 0.5
theta = temp_r * 2 * mask_1 + (1-temp_r) * 2 * (1 - mask_1)

radius_c=radius/np.cos(theta)

temp_r = np.mod (r/radius_c, 1.0)
mask_1 = temp_r < 0.5
r = radius_c * (temp_r * 2 * mask_1 + (1-temp_r) * 2 * (1 - mask_1))

theta = theta + angle

x1_mask = r * np.cos(theta) + center_x
y1_mask = r * np.sin(theta) + center_y

mask = x1_mask < 0
x1_mask = x1_mask * (1 - mask)
mask = x1_mask > (col - 1)
x1_mask = x1_mask * (1 - mask) + (x1_mask * 0 + col -2) * mask

mask = y1_mask < 0
y1_mask = y1_mask * (1 - mask)
mask = y1_mask > (row -1)
y1_mask = y1_mask * (1 - mask) + (y1_mask * 0 + row -2) * mask

img_out = img * 1.0

int_x = np.floor (x1_mask)
int_x = int_x.astype(int)
int_y = np.floor (y1_mask)
int_y = int_y.astype(int)

p_mask = x1_mask - int_x
q_mask = y1_mask - int_y

img_out = img * 1.0

for ii in range(row):
    for jj in range (col):
        new_xx = int_x [ii, jj]
        new_yy = int_y [ii, jj]
#        p = p_mask[ii, jj]
#        q = q_mask[ii, jj]

        img_out[ii, jj, :] = img[new_yy, new_xx, :]

plt.figure (1)
plt.imshow (img)
plt.axis('off')

plt.figure (2)
plt.imshow (img_out)
plt.axis('off')

plt.show()


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

import projgrad

import sys
sys.path.append('../lib')
import plotting
from optdynlib import *

plt.style.use(['../optdynim.mplstyle'])

sigma = 0.025
#Delta = 0.1
Delta = 2.0 * sigma
N = int(1.0/Delta)
# ensure N is always even
N = N if N % 2 == 0 else N+1
x = np.linspace(0.0, 1.0, N, endpoint=False)
def func(x, sigma):
    return np.exp(- x**2 /  (2.0 * sigma**2))
F = build_1d_frp_matrix(func, x, sigma*np.ones(len(x)))

fig, ax = plt.subplots()

i = N//2
dp = np.linalg.inv(F).dot(ei(N, i))
dp /= np.sum(dp)

ax.plot((x-0.5)/sigma, dp, 'o-', label='$F^{-1} e_a$')

sigmacorr = 2*sigma
dpcorr = np.linalg.inv(F).dot(np.exp(-(Delta*(np.arange(N)-i))**2/(2*sigmacorr**2)))
dpcorr /= np.sum(dpcorr)
ax.plot((x-0.5)/sigma, dpcorr, 'o-', label='$F^{-1} f_a$')
ax.set_xlabel('$x/\sigma$')
ax.set_ylabel('relative update')
ax.set_xlim(-10, 10)
ax.legend()
plotting.despine(ax)
fig.tight_layout()
fig.savefig('figS4.svg')
fig.savefig('figS4.png', dpi=300)


import math as m
import numpy as np

def theFunction(x):
    return x**4 - 2*x + 1

n = 10
limite_inferior = 0
limite_superior = 2
delta_x = (limite_superior - limite_inferior) / n

# integral simple
suma = 0
for i in range(1, n):
    suma += theFunction(limite_inferior + i * delta_x)

suma = delta_x * (0.5*(theFunction(limite_inferior) +
                       theFunction(limite_superior)) + suma)
print('for loop', suma)

# regla simpson
suma_1 = 0
for i in range(1, (int)(n / 2) + 1):
    suma_1 += theFunction(limite_inferior + (2 * i - 1) * delta_x)

suma_2 = 0
for i in range(1, (int)(n / 2)):
    suma_2 += theFunction(limite_inferior + 2 * i * delta_x)

suma = (1/3) * delta_x * (theFunction(limite_inferior) + theFunction(limite_superior) + 4 * suma_1 + 2 * suma_2)
print('simpson', suma)


import numpy as np
def sumDivisors(x):
    sum = 1
    j = x
    sqrt = int(np.sqrt(x))
    for i in range(2, sqrt):
        if j%i==0:
            #print(j, i, j/i)
            sum = sum + i
            sum = sum + (j/i)
    if sqrt*sqrt == x:
        sum = sum - sqrt
    #print(sum)
    return sum

def isAmicable(a, b):
    if sumDivisors(a) == b and sumDivisors(b) == a:
        return True
    else:
        return False
"""
def main():
    print(sumDivisors(8039))
    print(isAmicable(2,3))
"""
def main():
    sum = 0
    for i in range(1, 10000):
        for j in range(i+1, 10000):
            truth = isAmicable(i, j)
            if truth == True:
                print(i, j)
                sum = sum + i + j
    print(sum)

if __name__=="__main__":
    main()


import math
import numpy as np
from scipy.io import wavfile

print("Press 1 for sin wave")
print("Press 2 for cosine wave")
print("Press 3 for using custom audio file (wav format)")
opt = int(input("Enter option: "))

file = open("data.txt", "w+")

if (opt == 1):
    for i in np.linspace(0, 1, int(input("Enter number of elements: "))):
        file.writelines(str(math.sin(2*math.pi*2000*i))+"\n")
elif (opt == 2):
    for i in np.linspace(0, 1, int(input("Enter number of elements: "))):
        file.writelines(str(math.cos(2*math.pi*2000*i))+"\n")
elif (opt == 3):
    file_name = input("Enter audio file name: ")
    samplerate, data = wavfile.read(file_name)
    for i in data:
        file.writelines(str(i[0]) + "\n")


import numpy as np

def chol_factor(M):
    '''
    Cholesky LL' factorization.

    Input:
      M : input matrix
    Output
      L : lower triangular matrix (such that M=L*L')
    '''
    n = len(M)
    L = np.zeros((n, n))
    for i in range(0, n):
        val = M[i, i] - np.dot(L[i, :],L[i, :])
        if val < 0:
            raise Exception('The matrix is not positive definite')
        L[i, i] = np.sqrt(val)
        for j in range(i+1, n):
            L[j, i] = (M[j, i] - np.dot(L[i, :],L[j, :])) / L[i, i]
    return L


#Calculating Probability Density Function and Cumulative distribution Function

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

x = np.linspace(-6,6,1000)

fx = norm.pdf(x, loc=0,scale =1)
# loc: mean scale: sd, use cdf instad of pdf for cdf and logpdf, logcdf

plt.plot(x,fx)
plt.show()


# -*- coding: utf-8 -*-

import numpy as np
from utils.ply import write_ply, read_ply
import time

def compute_plane(points):
    """
    Computing a plane passing through 3 input points

    Parameters
    ----------
    points : 3x3 numpy array (3 points stacked in a row-wise way)

    Returns
    -------
    point : a point in the found plane
    normal : a unit normal vector of the found plane
    """

    normal = np.cross(points[1] - points[0], points[2] - points[0])
    normal = normal / np.sqrt(np.sum(normal**2))

    point = points[0]

    return point, normal

def in_plane(points, normals, ref_pt, ref_normal, threshold_in=0.1, threshold_normals=0.8):
    """
    Checks whether the given points belong to a given plane (with some threshold value)

    Parameters
    ----------
    points : Nx3 numpy array
    normals : estimation of local normals at each point
    ref_pt : 3-numpy array (a point of the plane)
    ref_normal : 3-numpy array (unit vector of the plane)
    threshold_in : float: maximum distance to the plane for points to belong to it
    threshold_normals : float : if normals is provided, the angle between the normals of the plane
                        should not be greater than this threshold

    Returns
    -------
    indices : N-numpy array of booleans telling which points belong to the plane
    """
    dists = np.einsum("i,ji->j", ref_normal, points - ref_pt)
    indices = abs(dists) < threshold_in
    if normals is not None:
        normal_check = abs(np.dot(ref_normal, normals.T)) > threshold_normals
        return indices & normal_check
    return indices

def RANSAC(points, normals=None, NB_RANDOM_DRAWS=100, threshold_in=0.1, threshold_normals=0.8):
    """
    Applies the RANSAC algorithm to find an horizontal plane

    Parameters
    ----------
    points : Nx3 numpy array
    normals: Nx3 numpy array, optional (estimation of local normals at each point)
    NB_RANDOM_DRAWS : number of tries: the biggest plane of all draws will be taken
    threshold_in : float : distance threshold telling whether a point belongs to a plane or not
    threshold_normals : float : if normals is provided, the angle between the normals of the plane
                        should not be greater than this threshold, moreover the projection of the
                        normal of the plane on z axis should be greater than this threshold

    Returns
    -------
    best_ref_pt : 3-numpy array (point belonging to the best found plane)
    best_normal : 3-numpy array (unit normal vector of the best found plane)
    """

    best_ref_pt = np.zeros((3,1))
    best_normal = np.zeros((3,1))
    best_nb = -1

    for i in range(NB_RANDOM_DRAWS):
        # Drawing 3 different point indices at random
        rand_indices = np.zeros(3).astype(int)
        while len(np.unique(rand_indices)) != 3:
            rand_indices = np.random.randint(0, np.shape(points)[0], size=3)

        # Extracting the corresponding points
        pts = points[rand_indices]

        # Finding the associated plane
        ref_pt, ref_normal = compute_plane(pts)

        # Couting the number of points in this plane
        nb = np.sum(in_plane(points, normals, ref_pt, ref_normal, threshold_in))

        # Updating the best plane if needed
        if nb > best_nb and abs(ref_normal[2]) > threshold_normals:
            best_nb = nb
            best_ref_pt = ref_pt
            best_normal = ref_normal

    return best_ref_pt, best_normal


import numpy as np
import pandas as pd

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

def softmax(x):
    x = x - x.max(axis=1, keepdims=True)
    return np.exp(x)/np.sum(np.exp(x),axis=1, keepdims=True)

df = pd.read_csv("adult.data.txt", names=["age","workclass","fnlwgt","education","education-num","marital-status"
    ,"occupation","relationship","race","sex","capital-gain","capital-loss","hours-per-week","native-country","class"])
dx = pd.read_csv("adult.test.txt", names=["age","workclass","fnlwgt","education","education-num","marital-status"
    ,"occupation","relationship","race","sex","capital-gain","capital-loss","hours-per-week","native-country","class"])

for lf in df:
    if df[lf].dtype == "object":
        df[lf] = df[lf].astype("category").cat.codes
        dx[lf] = dx[lf].astype("category").cat.codes
    else :
        df[lf] = (df[lf] - df[lf].mean())/(df[lf].max() - df[lf].min())
        dx[lf] = (dx[lf] - dx[lf].mean()) / (dx[lf].max() - dx[lf].min())

x = df.drop(columns=["class"])
y = df["class"].values
x_test = dx.drop(columns=["class"])
y_test = dx["class"].values

multi_y = np.zeros((y.size, y.max()+1))
multi_y[np.arange(y.size), y] = 1
multi_y_test = np.zeros((y_test.size, y_test.max()+1))
multi_y_test[np.arange(y_test.size), y_test] = 1

inputSize = len(x.columns)
numberOfNodes = 150
numberOfClass = y.max() + 1
numberOfExamples = x.shape[0]

w1 = np.random.random_sample(size=(inputSize, numberOfNodes))
b1 = np.random.random_sample(numberOfNodes)
w2 = np.random.random_sample(size=(numberOfNodes, numberOfClass))
b2 = np.random.random_sample(numberOfClass)

batchSize = 32
trainNum = 150
learningRate = 0.01

# Start Training
for k in range(trainNum + 1):
    cost = 0
    accuracy = 0
    for i in range(int(numberOfExamples/batchSize)):
        # Forward-Propagation
        z = x[i * batchSize : (i+1) * batchSize]
        z_y = multi_y[i * batchSize : (i+1) * batchSize]
        layer1 = np.matmul(z, w1) + b1
        sig_layer1 = sigmoid(layer1)
        layer2 = np.matmul(sig_layer1, w2) + b2
        soft_layer2 = softmax(layer2)
        pred = np.argmax(soft_layer2, axis=1)
        # Cost Function: Cross-Entropy loss
        cost += -(z_y * np.log(soft_layer2 + 1e-9) + (1-z_y) * np.log(1 - soft_layer2 + 1e-9)).sum()
        accuracy += (pred == y[i * batchSize : (i + 1) * batchSize]).sum()

        # Back-Propagation
        dlayer2 = soft_layer2 - multi_y[i * batchSize : (i+1) * batchSize]
        dw2 = np.matmul(sig_layer1.T, dlayer2) / batchSize
        db2 = dlayer2.mean(axis=0)
        dsig_layer1 = (dlayer2.dot(w2.T))
        dlayer1 = sigmoid(layer1) * (1 - sigmoid(layer1)) * dsig_layer1
        dw1 = np.matmul(z.T, dlayer1) / batchSize
        db1 = dlayer1.mean(axis=0)

        w2 -= learningRate * dw2
        w1 -= learningRate * dw1
        b2 -= learningRate * db2
        b1 -= learningRate * db1
    if k % 10 == 0 :
        print("-------- # : {} ---------".format(k))
        print("cost: {}".format(cost/numberOfExamples))
        print("accuracy: {} %".format(accuracy/numberOfExamples * 100))

# Test the trained model
test_cost = 0
test_accuracy = 0
# Forward-Propagation
layer1 = np.matmul(x_test, w1) + b1
sig_layer1 = sigmoid(layer1)
layer2 = np.matmul(sig_layer1, w2) + b2
soft_layer2 = softmax(layer2)
pred = np.argmax(soft_layer2, axis=1)
# Cost Function: Cross-Entropy loss
test_cost += -(multi_y_test * np.log(soft_layer2 + 1e-9) + (1-multi_y_test) * np.log(1 - soft_layer2 + 1e-9)).sum()
test_accuracy += (pred == y_test).sum()

print("---- Result of applying test data to the trained model")
print("cost: {}".format(test_cost/numberOfExamples))
print("accuracy: {} %".format(test_accuracy/numberOfExamples * 100))


#Vamos utilizar a formula de black scholes merton para derivativos no mercado de opcoes
import numpy as np
import pandas as pd
from pandas_datareader import data as wb
from scipy.stats import norm

#Vamos utilizar as formulas do d1 e d2 para efetuar o calculo de BSM
#S = preço da acao
#K = preco de exercicio
#r = taxa livre de risco
#stdev = desvio padrao
#T = intervalo de tempo (anos)

def d1(S, K, r, stdev, T):
    return (np.log(S/K) + (r + stdev ** 2 / 2) * T) / (stdev * np.sqrt(T))

def d2(S, K, r, stdev, T):
    return (np.log(S/K) + (r - stdev ** 2 / 2) * T) / (stdev * np.sqrt(T))

#Vamos utilizar a distribuiçao normal cumulativa (cdf)
#Mostra como os dados se acumulam no tempo
#norm.cdf(0)

def BSM(S, K, r, stdev, T):
    return (S * norm.cdf(d1(S, K, r, stdev, T))) - (K * np.exp(-r * T) * norm.cdf(d2(S, K, r, stdev, T)))

ticker = 'PG'
data = pd.DataFrame()
data[ticker] = wb.DataReader(ticker, data_source='yahoo', start='2007-1-1', end='2017-3-21')['Adj Close']

S = data.iloc[-1]
log_returns = np.log(1 + data.pct_change())

stdev = log_returns.std() * 250 ** 0.5

#Aqui estamos atribuindo valores para os parametros
r = 0.025
K = 110.0
T = 1


import numpy as np
from scipy.constants import mu_0, epsilon_0

# useful params
def omega(freq):
    """Angular frequency, omega"""
    return 2.*np.pi*freq

def k(freq, sigma, mu=mu_0, eps=epsilon_0):
    """ Eq 1.47 - 1.49 in Ward and Hohmann """
    w = omega(freq)
    alp  = w * np.sqrt( mu*eps/2 * ( np.sqrt(1. + (sigma / (eps*w))**2 ) + 1) )
    beta = w * np.sqrt( mu*eps/2 * ( np.sqrt(1. + (sigma / (eps*w))**2 ) - 1) )
    return alp - 1j*beta

def TriangleFun(time, ta, tb):
    """
        Triangular Waveform
        * time: 1D array for time
        * ta: time at peak
        * tb: time at step-off
    """
    out = np.zeros(time.size)
    out[time<=ta] = 1/ta*time[time<=ta]
    out[(time>ta)&(time<tb)] = -1/(tb-ta)*(time[(time>ta)&(time<tb)]-tb)
    return out

def TriangleFunDeriv(time, ta, tb):
    """
        Derivative of Triangular Waveform
    """
    out = np.zeros(time.size)
    out[time<=ta] = 1/ta
    out[(time>ta)&(time<tb)] = -1/(tb-ta)
    return out

def SineFun(time, ta):
    """
        Sine Waveform
        * time: 1D array for time
        * ta: Pulse Period
    """
    out = np.zeros(time.size)
    out[time<=ta] = np.sin(1./ta*np.pi*time[time<=ta])

    return out

def SineFunDeriv(time, ta):
    """
        Derivative of Sine Waveform
    """
    out = np.zeros(time.size)
    out[time<=ta] = 1./ta*np.pi*np.cos(1./ta*np.pi*time[time<=ta])
    return out

def VTEMFun(time, ta, tb, a):
    """
        VTEM Waveform
        * time: 1D array for time
        * ta: time at peak of exponential part
        * tb: time at step-off
    """
    out = np.zeros(time.size)
    out[time<=ta] = (1-np.exp(-a*time[time<=ta]/ta))/(1-np.exp(-a))
    out[(time>ta)&(time<tb)] = -1/(tb-ta)*(time[(time>ta)&(time<tb)]-tb)
    return out


# -*- coding: UTF-8 -*-
# !/usr/bin/python
# @time     :2019/4/3 10:36
# @author   :Mo
# @function :TS-SS distance
# @url      :https://github.com/taki0112/Vector_Similarity
# @paper    :A Hybrid Geometric Approach for Measuring Similarity Level Among Documents and Document Clustering

import numpy as np
import math

zero_bit = 0.000000001

def Cosine(vec1, vec2):
    """
       余弦相似度
    :param vec1: arrary
    :param vec2: arrary
    :return: float
    """
    result = InnerProduct(vec1, vec2) / (VectorSize(vec1) * VectorSize(vec2) + zero_bit)
    return result

def VectorSize(vec):
    vec_pow = sum(math.pow(v + zero_bit, 2) for v in vec)
    if vec_pow >= 0:
        return math.sqrt(vec_pow)
    else:
        return zero_bit

def InnerProduct(vec1, vec2):
    try:
        return sum(v1 * v2 for v1, v2 in zip(vec1, vec2))
    except:
        return zero_bit

def Euclidean(vec1, vec2):
    vec12_pow = sum(math.pow((v1 - v2), 2) for v1, v2 in zip(vec1, vec2))
    if vec12_pow >= 0:
        return math.sqrt(vec12_pow)
    else:
        return zero_bit

def Theta(vec1, vec2):
    cosine_vec12 = Cosine(vec1, vec2)
    if -1 <= cosine_vec12 and cosine_vec12 <= 1:
        return math.acos(cosine_vec12) + 10
    else:
        return zero_bit + 10

def Triangle(vec1, vec2):
    theta = math.radians(Theta(vec1, vec2))
    return (VectorSize(vec1) * VectorSize(vec2) * math.sin(theta)) / 2

def Magnitude_Difference(vec1, vec2):
    return abs(VectorSize(vec1) - VectorSize(vec2))

def Sector(vec1, vec2):
    ED = Euclidean(vec1, vec2)
    MD = Magnitude_Difference(vec1, vec2)
    theta = Theta(vec1, vec2)
    return math.pi * math.pow((ED + MD), 2) * theta / 360

def TS_SS(vec1, vec2):
    return Triangle(vec1, vec2) * Sector(vec1, vec2)

if __name__ == '__main__':
    vec1_test = np.array([1, 38, 17, 32])
    vec2_test = np.array([5, 6, 8, 9])

    print(Euclidean(vec1_test, vec2_test))
    print(Cosine(vec1_test, vec2_test))
    print(TS_SS(vec1_test, vec2_test))


from __future__ import print_function, division

import numpy as np

def gram_schmidt(ws):
    vs = ws.copy()
    num_vectors = ws.shape[1]
    # orthogonize
    for i in range(num_vectors):
        for j in range(i):
            vs[:, i] -= vs[:, j].dot(ws[:, i])/(vs[:, j].dot(vs[:, j]))*vs[:, j]
    # normalize
    for i in range(num_vectors):
        vs[:, i] /= np.linalg.norm(vs[:, i])
    return vs

def qr(A):
    # A = S_id_B
    Q = gram_schmidt(A) # = S_id_B'
    # dabei ist die basiswechselmatrix von B nach B' eine obere dreiecksmatrix und damit auch die
    # von B' nach B
    #             Q          R
    #             |          |
    #             V          V
    # Also A = S_id_B' * B'_id_B
    #          ~~~~~~
    #          Gramschmidt
    # => A = Q*R => Q^-1*A = R => (da Q orthogonal) Q'*A = R
    R = Q.transpose().dot(A)
    return Q, R

A =  np.array([[1,2.],[3,4]])
Q, R = qr(A)

print("A:\n", A, "\nQ:\n", Q, "\nR:\n", R, "\nQ*R:\n", Q.dot(R))


import numpy as np
import scipy.special as sp
import math
from NMLA import NMLA

## Test

# parameters
x0, y0 = 0.0, 0.0              # observation point
c0 = 1.0                     # wavespeed at observation point
omega = 1000.0               # frequency
Rest = 3.0                   # estimate of the distance from source to oberservation point

# Add source
xs, ys = 2, 2
rxy = lambda x, y: np.sqrt((x-xs)**2 + (y-ys)**2)
u = lambda x, y, omega: 1j/4*np.sqrt(omega)*sp.hankel1(0, omega*rxy(x,y))
ux = lambda x, y, omega: -1j/4*(omega**1.5)*sp.hankel1(1,omega*rxy(x,y))*(x-xs)/rxy(x,y)
uy = lambda x, y, omega: -1j/4*(omega**1.5)*sp.hankel1(1,omega*rxy(x,y))*(y-ys)/rxy(x,y)

# numerical and exact ray direction
est_ang = NMLA(x0,y0,c0,omega,Rest,u,ux,uy)
ex_ang = math.atan2(y0-ys,x0-xs) + 2*np.pi

# print result
print '\nThe exact ray direction:', ex_ang/np.pi, r'$\pi$', '\n'
print 'The ray direction estimated ny NMLA:', est_ang/np.pi, r'$\pi$', '\n'
print 'Relative error:', abs(est_ang - ex_ang)/abs(ex_ang)

# Compared to MPM, NMLA is more stable, it allows much more noisy level to the source, but MPM is very sensitive to the noise.


import numpy as np
import pandas as pd
import os
import matplotlib.pyplot as plt
import scipy.stats as st
from scipy.stats import ttest_ind, ttest_ind_from_stats

# Read the csv file
if os.path.exists("Georgiapeaches.csv"):
  georgia = pd.read_csv("Georgiapeaches.csv")
if os.path.exists("Yangshanpeaches.csv"):
  yangshan = pd.read_csv("Yangshanpeaches.csv")

# Prepare data
x = georgia['Yield per investment (in kilograms per Martian dollar)'].to_numpy()
y = yangshan['Yield per investment (in kilograms per Martian dollar)'].to_numpy()

mean_x = np.mean(x)
mean_y = np.mean(y)

sdx = np.std(x)
sdy = np.std(y)

n1 = x.size
n2 = y.size

#this is a helper variable to make the calculation cleaner
i = (np.square(sdx) / n1) + (np.square(sdy) / n2)

#calculating the test statistic

z = (mean_x - mean_y) / np.sqrt(i)
print (z)

# 90%
ci_x1 = st.t.interval(0.90, n1-1, loc=mean_x, scale=st.sem(x))
ci_y1 = st.t.interval(0.90, n2-1, loc=mean_y, scale=st.sem(y))
print ("The 90% confidence interval for Georgian peaches:", ci_x1)
print ("The 90% confidence interval for Yangshan peaches:", ci_y1)

# 95%
ci_x2 = st.t.interval(0.95, n1-1, loc=mean_x, scale=st.sem(x))
ci_y2 = st.t.interval(0.95, n2-1, loc=mean_y, scale=st.sem(y))
print ("The 95% confidence interval for Georgian peaches:", ci_x2)
print ("The 95% confidence interval for Yangshan peaches:", ci_y2)

# 99%
ci_x3 = st.t.interval(0.99, n1-1, loc=mean_x, scale=st.sem(x))
ci_y3 = st.t.interval(0.99, n2-1, loc=mean_y, scale=st.sem(y))
print ("The 99% confidence interval for Georgian peaches:", ci_x3)
print ("The 99% confidence interval for Yangshan peaches:", ci_y3)


import numpy as np

class MSE:
    @staticmethod
    def compute(a, y):
        y = y.reshape(1, -1)
        assert(a.shape == y.shape)
        m = a.shape[1]
        return np.sum((a - y) ** 2) / m

    @staticmethod
    def differentiate(a, y):
        return 2 * (a - y)


from sympy import ( symbols, solve, diff, integrate, exp, lambdify, pprint )
import matplotlib.pyplot as plt
import numpy as np

# The life (in months) of a certain electronic computer part has a probability density function defined by F,
# Find the probability that a randomly selected component will last the following lengths of time.

x = symbols( 'x' )
F = .5 * exp( -x / 2 )

# What does the life-span look like?
g_xlim = [ 1, 20 ]
g_ylim = [ -5, 15 ]

lam_p = lambdify( x, F, np )
x_vals = np.linspace( g_xlim[0], g_xlim[1], 1000, endpoint=True )
y_vals = lam_p( x_vals )
plt.plot( x_vals, y_vals )

# Probability it will last 8 months?

a, b = 4, 8
bounds = np.arange( a, b, 1/50., dtype=float)

for n in bounds:
	y = F.subs( { x: n } )
	plt.vlines( x = n, ymin = 0, ymax = y, color = 'Teal', zorder = 1, alpha = .4 )

area = integrate( F, ( x, a, b ) ).evalf()

total_area = integrate( F, ( x, 0, 100 ) ).evalf()

area_pct = round( ( area / total_area ), 4 )
plt.text( 2 , .1, 'Area: {0}%'.format( area_pct ) )

plt.show()

# Find the cumulative distribution function for this random variable.
a, b = 0, x
cdf = integrate( F, ( x, a, b ) )

pprint( cdf )

#  Use the answer to part C to find the probability that a randomly selected component will last at most 6 months.

ans = cdf.subs( { x: 6 } ).evalf()
round( ans, 4 )


import numpy as np
from sklearn import decomposition

# Define individual features
x1 = np.random.normal(size=250)
x2 = np.random.normal(size=250)
x3 = 2*x1 + 3*x2
x4 = 4*x1 - x2
x5 = x3 + 2*x4

# Create dataset with the above features
X = np.c_[x1, x3, x2, x5, x4]

# Perform Principal Components Analysis
pca = decomposition.PCA()
pca.fit(X)

# Print variances
variances = pca.explained_variance_
print('\nVariances in decreasing order:\n', variances)

# Find the number of useful dimensions
thresh_variance = 0.8
num_useful_dims = len(np.where(variances > thresh_variance)[0])
print('\nNumber of useful dimensions:', num_useful_dims)

# As we can see, only the 2 first components are useful
pca.n_components = num_useful_dims
X_new = pca.fit_transform(X)
print('\nShape before:', X.shape)
print('Shape after:', X_new.shape)


import numpy as np

class Loss:
    def calculate(self, y_pred, y_true):
        sample_losses = self.forward(y_pred, y_true)
        return np.mean(sample_losses)

class CategoricalCrossentropy(Loss):
    def forward(self, y_pred, y_true):
        n_samples = len(y_pred)
        y_pred_clipped = np.clip(a=y_pred, a_min=1e-7, a_max=1-1e-7)

        if len(y_true.shape) == 1:
            correct_confidences = y_pred_clipped[range(n_samples), y_true]
        elif len(y_true.shape) == 2:
            correct_confidences = np.sum(y_pred_clipped*y_true, axis=-1)

        negative_log_likelihoods = -np.log(correct_confidences)
        return negative_log_likelihoods

class Accuracy:
    def calculate(self, y_pred, y_true):
        preds = np.argmax(y_pred, axis=-1)
        return np.mean(preds == y_true)

# In[] Test the Code
if __name__ == "__main__":
    y_true = np.array([
        [.1, .2, .3, .4, .5],
        #[.1, .2, .3, .4, .5]
    ])
    y_pred = np.array([
        [.1, .3, .3, .7, .0],
        #[.1, .1, .1, .7, .0]
    ])
    err = CategoricalCrossentropy()
    print("Loss:", err.calculate(y_pred, y_true))


import numpy as np
import time

a = np.random.normal(5,5,(6,6))

def determinant(a):
    opp = a[0]
    l=len(opp)
    rr = list(range(l))
    if l==1:
        return opp
    else:

        trow = opp*(-1)**(np.array(rr))

        slices = [[i for i in rr if i != j] for j in rr]

        submats = np.array([a[1:,i] for i in slices])

        res = sum(np.array([determinant(submats[i])*trow[i] for i in rr]))

        return res

t0 = time.time()
determinant(a)[0]
t1=time.time()
print(t1-t0)

t0 = time.time()
np.linalg.det(a)
t1=time.time()
print(t1-t0)

def fact(x):
    if x==0:
        return 1
    else:
        return x*fact(x-1)

fact(6)


import numpy as np

def domainwall_analytic_solution(A, K, d, n_points):
    """
    Computes Neel domain wall magnetisation x component
    in absence of an external magnetic field.
    """
    x_array = np.linspace(0, d, n_points)
    mx_analytic = -np.tanh((x_array - d / 2.) / np.sqrt(A / K))

    return mx_analytic


#Contains functions that compute a statistic for a single HistoricData item from time
#offset+n through time offset.
import scipy.stats as sts

def variation_wrapper(hd, n=20, offset=0):
    """
    Calculates the variation on the closing price of hd from offset:offset+n
    """
    return sts.variation(hd.close[offset:offset+n])

def gain(hd, n=20, offset=0):
    """
    Calculates the gain over offset:offset+n in hd's closing prices
    """
    return ((hd.close[offset] - hd.close[offset+n]) / hd.close[offset+n])

def gain_vs_avg(hd, n=20, offset=0):
    """
    Calculates the gain of the closing price at offset vs the moving avg.
    """
    return ((hd.close[offset] - sma(hd, offset=offset)) / sma(hd, offset=offset))

def sma(hd, time_period=90, offset=0):
    """
    Returns the simple moving average for the stock over the specified period of time.
    Note: time_period is used instead of n since typically the time period here being
    used is greater than n.
    """
    if len(hd.close) >= offset+time_period:
        return sts.tmean(hd.close[offset:offset+time_period])
    else:
        return sts.tmean(hd.close[offset:])


import numpy as np
from matplotlib.ticker import NullFormatter, FormatStrFormatter, StrMethodFormatter
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches  # for legends
import pandas as pd
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
import datetime
from scipy.optimize import curve_fit

from sklearn.metrics import r2_score
from math import floor

# We'll use this later - x_max (in days elapsed) before ebola in a particular region switched from exponential to sigmoid
# (determined by inspection, 2-3 readings before daily new cases/deaths peaked)
X_CAPS = {
        "cases": { "total": 440, "guinea": 410, "liberia": 435, "sierraleone": 425, },
        "deaths": { "total": 435, "guinea": 400, "liberia": 465, "sierraleone": 420, },
    }

def display_evdefender_plots():
    # Load and select data from CSV
    data = pd.read_csv("data/coronavirus_data.csv")

    # select data for [Jan 27, Feb 2], matching @evdefender's second cases (not deaths!) plot
    window = data[["date", "cases_china_ex", "deaths_china_ex"]][7:14]

    # Fit quadratic and exp models to cases and deaths timeseries; find coeffs and R2s
    x = list(range(len(window)))  # 7 datapoints
    y, y_predicted, popt, r2, label = ({}, {}, {}, {}, {})
    def fquadratic(x, a, b, c):
        return a*x**2 + b*x + c
    def fexp(x, a, b):
        return a*(1+b)**x
    for fittype in ["quad", "exp"]:
        callback = fquadratic if fittype == "quad" else fexp
        y_predicted[fittype], popt[fittype], r2[fittype], label[fittype] = ({}, {}, {}, {})
        for kind in ["cases", "deaths"]:
            y[kind] = window["{}_china_ex".format(kind)].values
            popt[fittype][kind], _ = curve_fit(callback, x, y[kind])
            if fittype == "quad":
                y_predicted[fittype][kind] = [callback(x_i, popt[fittype][kind][0], popt[fittype][kind][1], popt[fittype][kind][2]) for x_i in x]
                label[fittype][kind] = "{}d^2 + {}d + {}".format(round(popt[fittype][kind][0], 2), round(popt[fittype][kind][1], 1), round(popt[fittype][kind][2], 1))
            elif fittype == "exp":
                y_predicted[fittype][kind] = [callback(x_i, popt[fittype][kind][0], popt[fittype][kind][1]) for x_i in x]
                label[fittype][kind] = "{}*(1+{})^d".format(round(popt[fittype][kind][0], 2), round(popt[fittype][kind][1], 4))
            r2[fittype][kind] = r2_score(y[kind], y_predicted[fittype][kind])
            label[fittype][kind] += "; R2 = {}".format(round(r2[fittype][kind], 5))

    # let's reproduce evdefender's mysteriously-truncated Feb 2 deaths plot as well, just to double-check the numbers
    kind = "deaths_trunc"
    for fittype in ["quad", "exp"]:
        callback = fquadratic if fittype == "quad" else fexp
        popt[fittype][kind], _ = curve_fit(callback, x[1:], y["deaths"][1:])  # skip first date, Jan 27
        if fittype == "quad":
            y_predicted[fittype][kind] = [callback(x_i, popt[fittype][kind][0], popt[fittype][kind][1], popt[fittype][kind][2]) for x_i in x[1:]]
            label[fittype][kind] = "{}d^2 + {}d + {}".format(round(popt[fittype][kind][0], 2), round(popt[fittype][kind][1], 1), round(popt[fittype][kind][2], 1))
        elif fittype == "exp":
            y_predicted[fittype][kind] = [callback(x_i, popt[fittype][kind][0], popt[fittype][kind][1]) for x_i in x[1:]]
            label[fittype][kind] = "{}*(1+{})^d".format(round(popt[fittype][kind][0], 2), round(popt[fittype][kind][1], 4))
        r2[fittype][kind] = r2_score(y["deaths"][1:], y_predicted[fittype][kind])
        label[fittype][kind] += "; R2 = {}".format(round(r2[fittype][kind], 5))

    # Plot fits for cases and deaths timeseries
    fig, axs = plt.subplots(3, sharex=True)  # three vertically-stacked subplots
    fig.suptitle("Recreation of @evdefender Feb 2 China cases/deaths timeseries fits")
    for i, kind in enumerate(["cases", "deaths_trunc", "deaths"]):
        if kind == "deaths_trunc":
            axs[i].scatter(x[1:], y["deaths"][1:], color='blue')
            axs[i].set(ylabel="Confirmed China {}\nex-HK, Macau, Taipei".format("Deaths (trunc.)"))
        else:
            axs[i].scatter(x, y[kind], color='blue')
            axs[i].set(ylabel="Confirmed China {}\nex-HK, Macau, Taipei".format(kind.capitalize()))
        axs[i].grid(axis='y')
        patches = []
        for fittype in ["quad", "exp"]:
            fittype_color = 'red' if fittype == "quad" else 'green'
            axs[i].plot(x[1:] if kind == "deaths_trunc" else x, y_predicted[fittype][kind], color=fittype_color)
            patches.append(mpatches.Patch(color=fittype_color, label=label[fittype][kind]))
        axs[i].legend(handles=patches)
    axs[0].set_xticks(x)
    axs[0].set_xticklabels(["Jan {}".format(k) for k in range(27, 32)] + ["Feb {}".format(k) for k in range(1, 3)])

    plt.show()
    return r2["quad"]

def display_ebola_plots():
    # Load data from CSV
    data = pd.read_csv("data/ebola_2014_data.csv")

    # Convert dates from strings to datetimes
    dates = data["date"].values
    datetimes = [datetime.datetime.strptime(datestr, '%d %b %Y') for datestr in dates]  # date of month, month abbrev., year
    days_elapsed = [(date - min(datetimes)).days for date in datetimes]

    # queue up plots - we'll add scatter plots and fits as we go
    fig, axs = plt.subplots(2, sharex=True)  # two vertically-stacked subplots
    fig.suptitle("Quality of sigmoid fits to 2014 West African ebola epidemic in total + 3 regions")

    x = days_elapsed

    # compute sigmoid fits for cases and deaths, for all four locs
    def fsigmoid(x, a, b, c):
        return c / (1 + np.exp(-a*(x-b)))
    results = {"popt": {}, "pcov": {}, "labels": {}}
    colors = {
            "total": ["blue", "blue"],
            "guinea": ["red", "red"],
            "liberia": ["green", "green"],
            "sierraleone": ["black", "black"],
            }
    p0 = [[2.2e-02, 2.3e+02, 2.0e+04],
          [1.2e-02, 2.0e+02, 1.1e+04]]  # from observation from previous runs with no p0
    for kind in ["cases", "deaths"]:
        isdeaths = 1 if kind == "deaths" else 0
        results["popt"][kind] = {}
        results["pcov"][kind] = {}
        results["labels"][kind] = {}
        patches = []
        for loc in colors.keys():
            y = data["{}_{}".format(kind, loc)].values
            popt, pcov = curve_fit(fsigmoid, days_elapsed, y, p0 = p0[isdeaths])
            results["popt"][kind][loc] = popt
            results["pcov"][kind][loc] = pcov

            axs[isdeaths].scatter(x, y, color = colors[loc][0])
            y_predicted = [fsigmoid(x_i, popt[0], popt[1], popt[2]) for x_i in x]
            axs[isdeaths].plot(x, y_predicted, color = colors[loc][1])

            label = "{}: {}/(1 + exp({:.3f}*(x-{})))".format(loc, round(popt[2], 1), round(popt[0], 3), round(popt[1], 1))
            label += "; R2 = {}".format(round(r2_score(y, y_predicted), 4))
            results["labels"][kind][loc] = label
            patches.append(mpatches.Patch(color=colors[loc][1], label=label))
        axs[isdeaths].legend(handles=patches)
        axs[isdeaths].grid(axis='y')
        axs[isdeaths].set(ylabel=kind.capitalize())
    axs[1].set(xlabel="Days elapsed")

    # Plot cases and death fits
    plt.show()
    return

def display_ebola_quadratic_samples(r2s_evdef):
    # Load data from CSV
    data = pd.read_csv("data/ebola_2014_data.csv")

    # Convert dates from strings to datetimes
    dates = data["date"][::-1].values
    datetimes = [datetime.datetime.strptime(datestr, '%d %b %Y') for datestr in dates]  # date of month, month abbrev., year
    days_elapsed = [(date - min(datetimes)).days for date in datetimes]

    # for each kind/loc combo, for each 6-long range of in-window reports, compute an R2 for a quadratic fit
    r2s = []
    for kind in ["cases", "deaths"]:
        for loc in ["total", "guinea", "liberia", "sierraleone"]:
            y_full = data["{}_{}".format(kind,loc)][::-1].values
            for i_min in [x for x in range(len(days_elapsed) - 7) if days_elapsed[x] <= X_CAPS[kind][loc] and y_full[x] > 0]:
                x = np.array(days_elapsed[i_min:i_min+7]).reshape(-1,1)
                y = y_full[i_min:i_min+7]
                poly = PolynomialFeatures(degree = 2)
                x_poly = poly.fit_transform(x)
                poly.fit(x_poly, y)
                lin2_reg = LinearRegression().fit(x_poly, y)

                r2 = lin2_reg.score(poly.fit_transform(x), y)
                r2s.append(r2)
    x = np.array(r2s)
    np.random.seed(0)  # make the jitter deterministic
    y = np.random.normal(0, 1, len(x))
    fig, ax = plt.subplots()
    fig.suptitle("Quadratic fit R2 distribution comparison between selected\n7-long Ebola epidemic windows and China [7-long] Feb 2 fits")
    ax.set_xscale('logit')
    ax.set_yticks([])
    ax.scatter(x, y, alpha=0.4)
    ax.set_ylim([-10, 10])
    ax.xaxis.set_major_formatter(FormatStrFormatter('%.4g'))
    ax.xaxis.set_minor_formatter(NullFormatter())
    ax.set_xticks([floor(min(r2s)*10.0) / 10, 0.9, 0.99, 0.999, 0.9999])
    # add the two points for @evdefender's cases and deaths R2 scores
    x = np.array([r2s_evdef["cases"], r2s_evdef["deaths"]])
    y = np.zeros_like(x)
    ax.scatter(x, y, color='red', marker='^')
    ax.annotate("Feb 2 China\ncases R2", (x[0], y[0]), textcoords="offset pixels", xytext=(0,-40), ha="center", color="red", fontsize=9, weight="bold")
    ax.annotate("Feb 2 China\ndeaths R2", (x[1], y[1]), textcoords="offset pixels", xytext=(0,-40), ha="center", color="red", fontsize=9, weight="bold")
    plt.show()
    return

def display_ebola_quadratic_split_samples(r2s_evdef):
    # Load data from CSV
    data = pd.read_csv("data/ebola_2014_data.csv")

    # Convert dates from strings to datetimes
    dates = data["date"][::-1].values
    datetimes = [datetime.datetime.strptime(datestr, '%d %b %Y') for datestr in dates]  # date of month, month abbrev., year
    days_elapsed = [(date - min(datetimes)).days for date in datetimes]

    # We'll color-code each R2 dot in the scatterplots, by **min** counts observed in its window; higher is better
    SAMPLE_QUALITY_COLOR = [
            (1, "brown"),
            (50, "blue"),
            (2500, "green"),
            ]

    fig, axs = plt.subplots(2, 4, sharex=True)  # 2 rows, 4 cols, 8 plots total
    fig.suptitle("Breakdown of quadratic fit R2 distribution comparison by\nkind, region, and min observation in window")
    for plot_row, kind in enumerate(["cases", "deaths"]):
        axs[plot_row][0].set(ylabel=kind)
        for plot_col, loc in enumerate(["total", "guinea", "liberia", "sierraleone"]):
            axs[1][plot_col].set(xlabel=loc)
            y_full = data["{}_{}".format(kind,loc)][::-1].values
            r2s = []
            colors = []
            for i_min in [x for x in range(len(days_elapsed) - 7) if days_elapsed[x] <= X_CAPS[kind][loc] and y_full[x] > 0]:
                # color it based on quality (e.g. >=1, >=5, >= 20 entries)
                # repeat analysis above but in a 4x2 (regions x cases/deaths) plot grid, and color-code scatterpoints
                x = np.array(days_elapsed[i_min:i_min+7]).reshape(-1,1)
                y = y_full[i_min:i_min+7]
                color = max([pair for pair in SAMPLE_QUALITY_COLOR if min(y) >= pair[0]])[1]
                colors.append(color)
                poly = PolynomialFeatures(degree = 2)
                x_poly = poly.fit_transform(x)
                poly.fit(x_poly, y)
                lin2_reg = LinearRegression().fit(x_poly, y)
                r2 = lin2_reg.score(poly.fit_transform(x), y)
                r2s.append(r2)
            x = np.array(r2s)
            np.random.seed(0)  # make the jitter deterministic
            y = np.random.normal(0, 1, len(x))
            axs[plot_row][plot_col].set_xscale('logit')
            axs[plot_row][plot_col].set_yticks([])
            axs[plot_row][plot_col].scatter(x, y, alpha=0.4, color=colors)
            axs[plot_row][plot_col].set_ylim([-10, 10])
            axs[plot_row][plot_col].xaxis.set_major_formatter(FormatStrFormatter('%.4g'))
            axs[plot_row][plot_col].xaxis.set_minor_formatter(NullFormatter())
            axs[plot_row][plot_col].set_xticks([0.7, 0.9, 0.99, 0.999, 0.9999])
            x = np.array([r2s_evdef[kind]])
            y = np.zeros_like(x)
            axs[plot_row][plot_col].scatter(x, y, color='red', marker='^')  # add R2 from China dataset for corresponding kind (cases, deaths)
            axs[plot_row][plot_col].annotate("China R2", (x[0], y[0]), textcoords="offset pixels", xytext=(0,-20), ha="center", color="red", fontsize=9, weight="bold")
    patches = [mpatches.Patch(color=pair[1], label='All observations in window >= {}'.format(pair[0])) for pair in SAMPLE_QUALITY_COLOR]
    fig.legend(handles=patches)
    plt.show()

if __name__ == "__main__":
    r2s_evdef = display_evdefender_plots()
    display_ebola_plots()
    display_ebola_quadratic_samples(r2s_evdef)
    display_ebola_quadratic_split_samples(r2s_evdef)


import numpy as np
from numba import jit
# from scipy.stats import norm

# @jit
# def pdf_skewnormal(x, location=0.0, scale=1.0, shape=0.0):
#     scale = scale ** 2
#     t = (x - location) / scale
#     return 2.0 / scale * norm.pdf(t) * norm.cdf(shape * t)

def backGroundPlaneEstimation(x, y, A, B, C):
    return A * x + B * y + C

def gauss2D(x, y, Amp, x_0, y_0, sigma_x, sigma_y, theta):
    theta = np.deg2rad(theta)
    a = np.cos(theta) ** 2 / (2 * sigma_x ** 2) + np.sin(theta) ** 2 / (2 * sigma_y ** 2)
    b = -np.sin(2 * theta) / (4 * sigma_x ** 2) + np.sin(2 * theta) / (4 * sigma_y ** 2)
    c = np.sin(theta) ** 2 / (2 * sigma_x ** 2) + np.cos(theta) ** 2 / (2 * sigma_y ** 2)
    g = Amp * np.exp(-(a * (x - x_0) ** 2 + 2 * b * (x - x_0) * (y - y_0) + c * (y - y_0) ** 2))
    return g

@jit
def fitFunc(xy, Amp, x_0, y_0, sigma_x, sigma_y, theta, A, B, C):
    x, y = xy
    g = gauss2D(x, y, Amp, x_0, y_0, sigma_x, sigma_y, theta)
    g += backGroundPlaneEstimation(x, y, A, B, C)
    return g

def NGauss(numOfGauss):
    def makeNGauss(xy, *parameters):
        xi, yi = xy
        g = 0
        gaussParams = parameters[3:]
        g += backGroundPlaneEstimation(xi, yi, parameters[0], parameters[1], parameters[2])
        for i in range(numOfGauss):
            g += gauss2D(xi, yi, gaussParams[i * 6], gaussParams[i * 6 + 1], gaussParams[i * 6 + 2],
                         gaussParams[i * 6 + 3], gaussParams[i * 6 + 4], gaussParams[i * 6 + 5])
        return g

    return makeNGauss

# @jit
# def fit2GaussFunc(xy, Amp_1, x_0_1, y_0_1, sigma_x_1, sigma_y_1, theta_1, Amp_2, x_0_2, y_0_2, sigma_x_2, sigma_y_2,
#                   theta_2, A, B, C):
#     x, y = xy
#     g = gauss2D(x, y, Amp_1, x_0_1, y_0_1, sigma_x_1, sigma_y_1, theta_1)
#     g += gauss2D(x, y, Amp_2, x_0_2, y_0_2, sigma_x_2, sigma_y_2, theta_2)
#     g += backGroundPlaneEstimation(x, y, A, B, C)
#     return g


from astropy.coordinates import Angle
from numpy import cos, sin, array

def rotation_matrix_2d(angle):
    """construct a 2D rotation matrix as a numpy NDArray that rotates a
    vector clockwise. Angle should be any object that can be converted
    into an `astropy.coordinates.Angle`
    """
    psi = Angle(angle).rad
    return array([[cos(psi), -sin(psi)],
                  [sin(psi),  cos(psi)]])


import numpy as np
from sklearn.datasets import load_breast_cancer

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

def activationDerivative(z):
    tmp = activation(z)

    return np.multiply(tmp, 1 - tmp)

def feedforward(x, Weight, bias):

    layer = len(Weight) - 1
    a = x

    for l in range(1, layer + 1):
        z = Weight[l].T * a + bias[l]
        a = activation(z)

    return a

def costFunction(y, predicted_y):
    return -((1 - y) * np.log(1 - predicted_y) + y * np.log(predicted_y))

def normalize(X):
    """
    Normalize each input feature

    :param X:
    :return:
    """

    number_examples = X.shape[0]

    X_normalized = X - np.tile(np.mean(X, 0), [number_examples, 1])
    X_normalized = np.divide(X_normalized, np.tile(np.std(X_normalized, 0), [number_examples, 1]))

    return X_normalized

'''
Step 0: Load the training dataset
'''

dataset = load_breast_cancer()
y = np.matrix(dataset.target).T
X = np.matrix(dataset.data)

number_examples = X.shape[0]
number_features = X.shape[1]

# Normalize each input feature
X_new = normalize(X)

print("Dimension of X (normalized): {}".format(X_new.shape))
print("Dimension of y: {}".format(y.shape))
print('\n')

'''
Step 1: Construct a neural network as follows:
- 4 layers with sigmoid activation functions
- 6 units in 1st hidden layer
- 5 units in 2nd hidden layer
'''

hidden2 = 5
hidden1 = 6

# Dimension of np.matrix(Weights): 1x4
Weights = [[], np.random.normal(0, 0.1, [number_features, hidden1]),
           np.random.normal(0, 0.1, [hidden1, hidden2]),
           np.random.normal(0, 0.1, [hidden2, 1])]

# Dimension of np.matrix(Biases): 1x4
Biases = [[], np.random.normal(0, 0.1, [hidden1, 1]),
          np.random.normal(0, 0.1, [hidden2, 1]),
          np.random.normal(0, 0.1, [1, 1])]

number_layers = len(Weights) - 1

'''
Step 2: Implement the stochastic gradient descent with:
- learning rate = 0.01
- max iteration = 1,000
'''

learning_rate = 0.01
max_iteration = 1000

for iteration in range(0, max_iteration):
    loss_this_iter = 0
    order = np.random.permutation(number_examples)

    for i in range(0, number_examples):

        # Grab the pattern order[i]
        x_sample = X_new[order[i], :].T
        y_sample = y[order[i], 0]

        # Feed forward step
        activation_arrays = [x_sample]
        z_arr = [[]]
        delta = [[]]

        gradient_weights = [[]]
        gradient_biases = [[]]

        for l in range(1, number_layers + 1):
            z_arr.append(Weights[l].T * activation_arrays[l - 1] + Biases[l])
            activation_arrays.append(activation(z_arr[l]))

            # Just to give arrays the right shape for the backprop step
            delta.append([])
            gradient_weights.append([])
            gradient_biases.append([])

        loss_this_sample = costFunction(y_sample, activation_arrays[number_layers][0, 0])
        loss_this_iter = loss_this_iter + loss_this_sample

        # Backprop step
        delta[number_layers] = activation_arrays[number_layers] - y_sample

        for l in range(number_layers, 0, -1):
            gradient_biases[l] = delta[l].copy()
            gradient_weights[l] = activation_arrays[l - 1] * delta[l].T

            if l > 1:
                delta[l - 1] = np.multiply(activationDerivative(z_arr[l - 1]),
                                           Weights[l] * delta[l])

        for l in range(1, number_layers + 1):
            Weights[l] = Weights[l] - learning_rate * gradient_weights[l]
            Biases[l] = Biases[l] - learning_rate * gradient_biases[l]

    print('\n')
    print('Iteration %d loss %f' % (iteration, loss_this_iter))


import sympy as sp
import matplotlib.pyplot as plt

def lagrange (x_array, y_array):
    x = sp.symbols('x')
    result = 0
    for i in range(len(x_array)):
        temp = 1
        for j in range(len(x_array)):
            if j != i:
                temp *= ((x - x_array[j]) / (x_array[i] - x_array[j]))
        result += temp * y_array[i]
    return sp.simplify(result)

x_array = [0.1, 0.3, 0.5, 0.7, 0.9, 1.1]
y_array = [18.559624, 22.000392, 25.925000, 30.007048, 33.505416, 31.895624]

result = lagrange(x_array, y_array)
print(result)

x = sp.symbols("x")
sp.plot(result, (x, 0.1, 1.1))


import numpy as np
import matplotlib.pyplot as plt
import image_load as im
import activation as ac
data = 'data/c.jpg'
image_pad = np.pad(im.load_image(data), (2,2), mode='constant', constant_values=0)
print('Image with padding:',image_pad.shape)

"""
Kernels (filters)
with size 3x3 for edge detection
"""

kernel_1 = np.array([[1, 0, -1], [0, 0, 0], [-1, 0, 1]])
kernel_2 = np.array([[0, 1, 0], [1, -4, 1], [0, 1, 0]])
kernel_3 = np.array([[-1, -1, -1], [-1, 8, -1], [-1, -1, -1]])

print("Kernel 3x3 : ",kernel_1.shape,kernel_2.shape,kernel_3.shape)

# Preparing zero output arrays for filtered images

output_image1 = np.zeros(im.load_image(data).shape)
output_image2 = np.zeros(im.load_image(data).shape)
output_image3 = np.zeros(im.load_image(data).shape)

def pixels(arr):
    """

    Values that are more than 255

    """
    # Creating an empty array
    empty = np.empty(arr.shape)
    # Filling array with 255 value for all elements
    empty.fill(255)
    # has to be less than appropriate element in 'empty'
    result = np.where(arr < empty, arr, empty)
    return result

# Implementing convolution operation for Edge detection for GrayScale image

for i in range(image_pad.shape[0]-4):
    for j in range(image_pad.shape[1]-4):
        input_image = image_pad[i:i+3, j:j+3]
        output_image1[i,j] = np.sum(input_image*kernel_1)
        output_image2[i,j] = np.sum(input_image*kernel_2)
        output_image3[i, j] = np.sum(input_image * kernel_3)

output_image1 = pixels(ac.relu(output_image1))
output_image2 = pixels(ac.relu(output_image2))
output_image3 = pixels(ac.relu(output_image3))

def Conv():
    """

    """
    f, axarr = plt.subplots(2, 2, figsize=(10, 10))
    #plt.set_cmap('gray')
    f.suptitle('Kernel 3x3', fontsize=16)
    axarr[0, 0].imshow(im.original(data))
    axarr[0,0].set_ylabel('Original image')
    #
    axarr[0, 1].imshow(output_image1)

    #
    axarr[1, 0].imshow(output_image2)

    #
    axarr[1, 1].imshow(output_image3)

    plt.show()
Conv()


"""Moran process."""
import numpy as np

from stochastic.processes.base import BaseSequenceProcess

class MoranProcess(BaseSequenceProcess):
    """Moran process.

    .. image:: _static/moran_process.png
        :scale: 50%

    A neutral drift Moran process, typically used to model populations. At
    each step this process will increase by one, decrease by one, or remain
    at the same value between values of zero and the number of
    states, :math:`n`. The process ends when its value reaches zero or the
    maximum valued state.

    :param int maximum: the maximum possible value for the process.
    :param numpy.random.Generator rng: a custom random number generator
    """

    def __init__(self, maximum, rng=None):
        super().__init__(rng=rng)
        self.maximum = maximum
        self.p = self._probabilities(maximum)

    def __str__(self):
        return "Moran process with %s states" % self._maximum

    def __repr__(self):
        return "MoranProcess(maximum={n})".format(n=str(self.maximum))

    @property
    def maximum(self):
        """Maximum value."""
        return self._maximum

    @maximum.setter
    def maximum(self, value):
        if not isinstance(value, int):
            raise TypeError("Number of states must be an integer.")
        if value <= 2:
            raise ValueError("Number of states must be at least 3.")
        self._maximum = value

    def _probabilities(self, n):
        """Generate the transition probabilities for state :math:`n`.

        :param int n: the current state for which to generate transition
            probabilities.
        """
        probabilities = []
        for k in range(1, n):
            p_down = 1.0 * (n - k) / n * k / n
            p_up = 1.0 * k / n * (n - k) / n
            p_same = 1.0 - p_down - p_up
            probabilities.append([p_down, p_same, p_up])

        return probabilities

    def _sample_moran_process(self, n, start):
        """Generate a realization of the Moran process.

        Generate a Moran process until absorption occurs (state 0 or n) or
        length of process reaches length :math:`maximum`.
        """
        if not isinstance(start, int):
            raise TypeError("Initial state must be a positive integer.")
        if start < 0 or start > self.maximum:
            raise ValueError("Initial state must be between 0 and " + str(self.maximum))

        if not isinstance(n, int):
            raise TypeError("Sample length must be positive integer.")
        if n < 1:
            raise ValueError("Sample length must be at least 1.")

        s = [start]
        increments = [-1, 0, 1]
        for k in range(n - 1):
            if start in [0, self.maximum]:
                break
            start += self.rng.choice(increments, p=self.p[start - 1])
            s.append(start)

        return np.array(s)

    def sample(self, n, start):
        """Generate a realization of the Moran process.

        Generate a Moran process until absorption occurs (state 0
        or :py:attr:`maximum`) or length of process reaches length :math:`n`.

        :param int n: the maximum number of steps to generate assuming
            absorption does not occur.
        :param int start: the initial state of the process.
        """
        return self._sample_moran_process(n, start)


# exponential distribution

# used for describing time till next event e.g failure / success etc.

# It has two parameters.
# scale - inverse of rate (see lam in poisson distribution) defaults to 1.0
# size - The shape of the returned array

# draw out a sample for exponential distribution with 2.0 scale with 2x3 size

from numpy import random

x = random.exponential(scale = 2, size = (2,3))

print(x)

# visualization of exponential distribution

# from numpy import random
import matplotlib.pyplot as plt
import seaborn as  sns

sns.distplot(random.exponential(size = 1000), hist = False)
plt.show

# Relationship between Poisson and exponential distribution

# poisson distribution deals with the number of occurences of an event in a time peroid
# whereas exponential distribution deals with the time between these events


"""
https://en.wikipedia.org/wiki/Rayleigh_quotient
"""
from typing import Any

import numpy as np

def is_hermitian(matrix: np.ndarray) -> bool:
    """
    Checks if a matrix is Hermitian.
    >>> import numpy as np
    >>> A = np.array([
    ... [2,    2+1j, 4],
    ... [2-1j,  3,  1j],
    ... [4,    -1j,  1]])
    >>> is_hermitian(A)
    True
    >>> A = np.array([
    ... [2,    2+1j, 4+1j],
    ... [2-1j,  3,  1j],
    ... [4,    -1j,  1]])
    >>> is_hermitian(A)
    False
    """
    return np.array_equal(matrix, matrix.conjugate().T)

def rayleigh_quotient(A: np.ndarray, v: np.ndarray) -> Any:
    """
    Returns the Rayleigh quotient of a Hermitian matrix A and
    vector v.
    >>> import numpy as np
    >>> A = np.array([
    ... [1,  2, 4],
    ... [2,  3,  -1],
    ... [4, -1,  1]
    ... ])
    >>> v = np.array([
    ... [1],
    ... [2],
    ... [3]
    ... ])
    >>> rayleigh_quotient(A, v)
    array([[3.]])
    """
    v_star = v.conjugate().T
    v_star_dot = v_star.dot(A)
    assert isinstance(v_star_dot, np.ndarray)
    return (v_star_dot.dot(v)) / (v_star.dot(v))

def tests() -> None:
    A = np.array([[2, 2 + 1j, 4], [2 - 1j, 3, 1j], [4, -1j, 1]])
    v = np.array([[1], [2], [3]])
    assert is_hermitian(A), f"{A} is not hermitian."
    print(rayleigh_quotient(A, v))

    A = np.array([[1, 2, 4], [2, 3, -1], [4, -1, 1]])
    assert is_hermitian(A), f"{A} is not hermitian."
    assert rayleigh_quotient(A, v) == float(3)

if __name__ == "__main__":
    import doctest

    doctest.testmod()
    tests()


#! /usr/bin/env python

import numpy as np
from scipy.optimize import leastsq
from leastsqbound import leastsqbound

def func(p, x):
    """model data as y = m*x+b """
    m, b = p
    return m * np.array(x) + b

def err(p, y, x):
    return y - func(p, x)

# extract data
temp = np.genfromtxt("sample_data.dat")
x = temp[:, 0]
y = temp[:, 1]

# perform unbounded least squares fitting
p0 = [1.0, 0.0]
p, cov_x, infodic, mesg, ier = leastsq(err, p0, args=(y, x), full_output=True)

# print out results
print "Standard Least Squares fitting results:"
print "p:", p
print "cov_x:", cov_x
print "infodic['nfev']:", infodic['nfev']
print "infodic['fvec']:", infodic['fvec']
print "infodic['fjac']:", infodic['fjac']
print "infodic['ipvt']:", infodic['ipvt']
print "infodic['qtf']:", infodic['qtf']
print "mesg:", mesg
print "ier:", ier
print ""

# same as above using no bounds
p0 = [1.0, 0.0]
p, cov_x, infodic, mesg, ier = leastsqbound(err, p0, args=(y, x),
                                            full_output=True)

# print out results
print "Bounded Least Squares fitting with no bounds results:"
print "p:", p
print "cov_x:", cov_x
print "infodic['nfev']:", infodic['nfev']
print "infodic['fvec']:", infodic['fvec']
print "infodic['fjac']:", infodic['fjac']
print "infodic['ipvt']:", infodic['ipvt']
print "infodic['qtf']:", infodic['qtf']
print "mesg:", mesg
print "ier:", ier
print ""

# perform bounded least squares fitting
p0 = [1.0, 0.0]
bounds = [(0.0, 2.0), (-10.0, 10.0)]
p, cov_x, infodic, mesg, ier = leastsqbound(err, p0, args=(y, x),
                                            bounds = bounds, full_output=True)

# print out results
print "Bounded Least Squares fitting results:"
print "p:", p
print "cov_x:", cov_x
print "infodic['nfev']:", infodic['nfev']
print "infodic['fvec']:", infodic['fvec']
print "infodic['fjac']:", infodic['fjac']
print "infodic['ipvt']:", infodic['ipvt']
print "infodic['qtf']:", infodic['qtf']
print "mesg:", mesg
print "ier:", ier


import sys
import os
from scipy import stats
import tenseal as ts
import numpy as np
from scipy.stats import t

sys.path.append(os.path.abspath('../../tensealstat'))

from tensealstat.tools_context import ToolsContext as tc
from tensealstat.algebra.algebra_numpy import AlgebraNumpy
from tensealstat.algebra.algebra_tenseal import AlgebraTenseal
from tensealstat.statistic.student_t_equal_variance import StudentTEqualVariance

statistic_generator = StudentTEqualVariance()
#
# This test follows https://en.wikipedia.org/w/index.php?title=Welch%27s_t-test&oldid=994214781#Examples
# Example 1
#

# 1 done by the key holder
context = tc.get_context_default()
algebra_tenseal = AlgebraTenseal(context)
algebra_numpy = AlgebraNumpy()

# 2 done by the data holders
sample_0 = np.array([27.5, 21.0, 19.0, 23.6, 17.0, 17.9, 16.9, 20.1, 21.9, 22.6, 23.1, 19.6, 19.0, 21.7, 21.4])
sample_1 = np.array([27.1, 22.0, 20.8, 23.4, 23.4, 23.5, 25.8, 22.0, 24.8, 20.2, 21.9, 22.1, 22.9, 20.5, 24.4])

list_sample = [sample_0, sample_1]
list_sample_encrypted = [algebra_tenseal.encrypt_vector(sample) for sample in list_sample]

# 3 done by the agregator
statistic_encrypted = statistic_generator.encrypt_statistic(algebra_tenseal, list_sample_encrypted)

# # 4 done by the key holder
t_statistic, degrees_of_freedom = statistic_generator.decrypt_statistic(algebra_tenseal, statistic_encrypted)
p_value = t.cdf(t_statistic, degrees_of_freedom)
# Assert.IsTrue(chi2_statistic ~= -2.46)
# Assert.IsTrue(p_value ~= 0.010)
print('')
print('via tensealstattest')
print('t_statistic: ' + str(t_statistic))
print('p_value: ' + str(p_value))

# Test version
statistic_encrypted = statistic_generator.encrypt_statistic(algebra_numpy, list_sample)
t_statistic, degrees_of_freedom = statistic_generator.decrypt_statistic(algebra_numpy, statistic_encrypted)
p_value = t.cdf(t_statistic, degrees_of_freedom)
# Assert.IsTrue(chi2_statistic ~= -2.46)
# Assert.IsTrue(p_value ~= 0.010)
print('')
print('via tensealstat')
print('t_statistic: ' + str(t_statistic))
print('p_value: ' + str(p_value))

t_statistic, p_value = stats.ttest_ind(sample_0, sample_1, equal_var=True)
print('')
print('via scipy')
print('t_statistic: ' + str(t_statistic))
print('p_value: ' + str(p_value / 2))


"""Exactly solvable single-electron hydrogen-like atom."""
from typing import Callable, Union

import flax
import jax.numpy as jnp

import vmcnet.models as models
import vmcnet.physics as physics
from vmcnet.utils.typing import Array, P, ModelApply

class HydrogenLikeWavefunction(models.core.Module):
    """Model which computes -decay_rate * r, with trainable decay_rate.

    This model returns log|psi(x)|, where psi is the 1-s orbital exp(-decay_rate * r).
    This psi is an eigenfunction of the hydrogen-like Hamiltonian (one ion and one
    electron) when the decay rate is equal to 2 * nuclear_charge / (d - 1), with d > 1,
    where d is the dimension of the system.

    Thus when the system is 3-d, then this model computes the ground-state wavefunction
    precisely when decay_rate = nuclear_charge.

    Attributes:
        decay_rate (jnp.float32): initial decay rate in the model
    """

    init_decay_rate: jnp.float32

    @flax.linen.compact
    def __call__(self, x: Array) -> Array:  # type: ignore[override]
        """Log of isotropic exponential decay. Computes -decay_rate * ||x||.

        Args:
            x (Array): single electron positions, of shape (..., 1, d), where d
                is the dimension of the system

        Returns:
            Array: log of exponential decay wavefunction, with shape x.shape[:-2]
        """
        r = jnp.linalg.norm(x, axis=-1)
        scaled_r = models.core.Dense(
            1,
            kernel_init=lambda key, shape, **kwargs: jnp.array(
                [[self.init_decay_rate]]
            ),
            use_bias=False,
        )(r)
        return -jnp.squeeze(scaled_r, axis=-1)

def make_hydrogen_like_local_energy(
    log_psi_apply: Callable[[P, Array], Union[jnp.float32, Array]],
    charge: jnp.float32,
    d: int = 3,
) -> ModelApply[P]:
    """Local energy calculation for the hydrogen-like atom in general dimension d.

    Args:
        log_psi_apply (Callable): a function which computes log|psi(x)| for single
            inputs x. It is okay for it to produce batch outputs on batches of x as long
            as it produces a single number for single x. Has the signature
            (params, single_x_in) -> log|psi(single_x_in)|
        charge (jnp.float32): charge of the nucleus
        d (int, optional): Dimension of the system (number of coordinates that each
            ion and electron has). Defaults to 3.

    Returns:
        Callable: local energy function which computes -0.5 nabla^2 psi / psi + (Z / r),
        where psi is the wavefn, and Z is the charge of the nucleus. Has the signature
        (params, x) -> local energy array of shape (x.shape[0],)
    """
    ion_location = jnp.zeros((1, d))
    ion_charge = jnp.array([charge])

    kinetic_fn = physics.kinetic.create_continuous_kinetic_energy(log_psi_apply)
    potential_fn = physics.potential.create_electron_ion_coulomb_potential(
        ion_location, ion_charge
    )

    return physics.core.combine_local_energy_terms([kinetic_fn, potential_fn])


import numpy as np

def generate_data(ym_per_pix, xm_per_pix):
    '''
    Generates fake data to use for calculating lane curvature.
    In your own project, you'll ignore this function and instead
    feed in the output of your lane detection algorithm to
    the lane curvature calculation.
    '''
    # Set random seed number so results are consistent for grader
    # Comment this out if you'd like to see results on different random data!
    np.random.seed(0)
    # Generate some fake data to represent lane-line pixels
    ploty = np.linspace(0, 719, num=720)  # to cover same y-range as image
    quadratic_coeff = 3e-4  # arbitrary quadratic coefficient
    # For each y position generate random x position within +/-50 pix
    # of the line base position in each case (x=200 for left, and x=900 for right)
    leftx = np.array([200 + (y**2)*quadratic_coeff + np.random.randint(-50, high=51)
                      for y in ploty])
    rightx = np.array([900 + (y**2)*quadratic_coeff + np.random.randint(-50, high=51)
                       for y in ploty])

    leftx = leftx[::-1]  # Reverse to match top-to-bottom in y
    rightx = rightx[::-1]  # Reverse to match top-to-bottom in y

    # Fit a second order polynomial to pixel positions in each fake lane line
    # Fit new polynomials to x,y in world space
    left_fit_cr = np.polyfit(ploty*ym_per_pix, leftx*xm_per_pix, 2)
    right_fit_cr = np.polyfit(ploty*ym_per_pix, rightx*xm_per_pix, 2)

    return ploty, left_fit_cr, right_fit_cr

def measure_curvature_real():
    '''
    Calculates the curvature of polynomial functions in meters.
    '''
    # Define conversions in x and y from pixels space to meters
    ym_per_pix = 30/720  # meters per pixel in y dimension
    xm_per_pix = 3.7/700  # meters per pixel in x dimension

    # Start by generating our fake example data
    # Make sure to feed in your real data instead in your project!
    ploty, left_fit_cr, right_fit_cr = generate_data(ym_per_pix, xm_per_pix)

    # Define y-value where we want radius of curvature
    # We'll choose the maximum y-value, corresponding to the bottom of the image
    y_eval = np.max(ploty)

    # Calculation of R_curve (radius of curvature)
    left_curverad = ((1 + (2*left_fit_cr[0]*y_eval*ym_per_pix +
                           left_fit_cr[1])**2)**1.5) / np.absolute(2*left_fit_cr[0])
    right_curverad = ((1 + (2*right_fit_cr[0]*y_eval*ym_per_pix +
                            right_fit_cr[1])**2)**1.5) / np.absolute(2*right_fit_cr[0])

    return left_curverad, right_curverad

# Calculate the radius of curvature in meters for both lane lines
left_curverad, right_curverad = measure_curvature_real()

print(left_curverad, 'm', right_curverad, 'm')
# Should see values of 533.75 and 648.16 here, if using
# the default `generate_data` function with given seed number


import pandas as pd
from pandas import read_csv
import numpy
import matplotlib.pyplot as plot
from sklearn import model_selection
from sklearn import linear_model
from sklearn.preprocessing import LabelEncoder
from sklearn.metrics import mean_absolute_error

dataset = pd.read_csv("house_data.csv")
#print(dataset.shape)
#print(dataset.head(10))
print(dataset.describe())

dataset.hist()
#plot.show()

array=dataset.values
X=array[:,:5]
Y=array[:,5]

# here model will make 7 sets of data (as, seed=7 )
validation_size=0.20
seed=7
X_train,X_test,Y_train,Y_test=model_selection.train_test_split(X,Y,test_size=validation_size,random_state=seed)

# fitting the model
scoring='accuracy'
reg = linear_model.LinearRegression()
reg = reg.fit(X_train,Y_train)

predictions=reg.predict(X_test)  # predicts outcome(here house price) for the test dataset

# finding accuracy
accuracy = reg.score(X_test, Y_test) #finds the residual sum squared error, i.e; (1-u/v) where u = sum((y_test - y_pred)^2)
print("Accuracy = ",accuracy)        #and v is sum(( y_test - mean(y_test) )^2)
print("MAE: ", mean_absolute_error(Y_test,predictions))
print("RMSE: ", numpy.sqrt(mean_absolute_error(Y_test,predictions)))

## setting plot style
plot.style.use('ggplot')

## plotting residual errors in training data
plot.scatter(reg.predict(X_train), reg.predict(X_train) - Y_train,
            color = "green", s = 10, label = 'Train data')

## plotting residual errors in test data
plot.scatter(reg.predict(X_test), reg.predict(X_test) - Y_test,
            color = "blue", s = 10, label = 'Test data')

## plotting line for zero residual error
plot.hlines(y = 0, xmin = 0, xmax = 50, linewidth = 2)

## plotting legend
plot.legend(loc = 'upper right')

## plot title
plot.title("Residual error")

## function to show plot
plot.show()

fig, ax = plot.subplots()
ax.scatter(Y_test, predictions , edgecolors=(0, 0, 0))
ax.plot([Y_test.min(), Y_test.max()], [Y_test.min(), Y_test.max()], 'k--', lw=4)
ax.set_xlabel('Measured')
ax.set_ylabel('Predicted')
plot.show()

#predicting Absolute mean error
error = mean_absolute_error(Y_test , predictions  )

error = mean_absolute_error(Y_test , predictions  )
print('Mean Absolute error = ' , end='')
print(error)


import matplotlib
import numpy as np

def decoderBEC(RecievedM,ParityCheckMatrix):
    alpha=RecievedM
    n=len(RecievedM)
    syndrome=np.dot(ParityCheckMatrix,RecievedM)

    for z in range(50):
        tempalpha=alpha
        for i in range(0,n):
            if alpha[i]==-1:
                beta=np.zeros(n)
                SyndromeCount=0
                for j in range(0,np.size(ParityCheckMatrix,0)):
                    beta[0]=alpha[i]

                    if ParityCheckMatrix[j][i]==1:
                        SyndromeCount=SyndromeCount+1
                        sum=0
                        for k in range(0,n):
                            if ParityCheckMatrix[j][k]==1 and k!=i:
                                sum+=alpha[k]
                        sum=sum%2
                        beta[SyndromeCount]=sum

                Bincount=np.zeros(2)
                for  t in range(0,SyndromeCount+1):
                    if beta[t]==0:
                        Bincount[0]+=1
                    else:
                        Bincount[1]+=1

                if (Bincount[0]==Bincount[1]):
                    if (beta[0]==1):
                        tempalpha[i]=0
                    else:
                        tempalpha[i]=0

                elif Bincount[0]>Bincount[1]:
                   tempalpha[i]=0

                elif Bincount[0]<Bincount[1]:
                    tempalpha[i]=1

        alpha=tempalpha
        syndrome=(np.dot(ParityCheckMatrix,alpha))%2
        IsSyndromZero=np.count_nonzero(syndrome)

        if IsSyndromZero==0:
            break

    return alpha


import numpy as np

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

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

def tanh(x):
    return 2*sigmoid(2*x)-1

def leakyrelu(x,alpha=0.01):
    return np.maximum(alpha*x,x)

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


import numpy as np

def compress_image(image, num_values):
    """Compress an image using SVD and keeping the top `num_values` singular values.

    Args:
        image: numpy array of shape (H, W)
        num_values: number of singular values to keep

    Returns:
        compressed_image: numpy array of shape (H, W) containing the compressed image
        compressed_size: size of the compressed image
    """
    compressed_image = np.zeros_like(image)
    compressed_size = 0

    # Steps:
    #     1. Get SVD of the image
    #     2. Only keep the top `num_values` singular values, and compute `compressed_image`
    #     3. Compute the compressed size

    # 1. Get SVD of the image
    U, S, Vt = np.linalg.svd(image)
    # sigma = np.zeros((image.shape))
    # np.fill_diagonal(sigma, S)
    # print(np.isclose(U @ sigma @ Vt, image)) # True,...

    # 2. Only keep the top `num_values` singular values, and compute `compressed_image`
    for i in range(num_values):
        u = np.expand_dims(U[:,i], axis=1)    # m * 1
        s = S[i]
        v = np.expand_dims(Vt[i,:], axis=0)  # 1 * n
        compressed_image += (u*s).dot(v)      # plus partial A

    # 3. Compute the compressed size
    compressed_size = (U.shape[0] + 1 + Vt.shape[0]) * num_values   # (m + 1 + n) * k

    assert compressed_image.shape == image.shape, \
           "Compressed image and original image don't have the same shape"

    assert compressed_size > 0, "Don't forget to compute compressed_size"

    return compressed_image, compressed_size


from typing import Sequence

import numpy as np
import scipy.sparse as sp
from scipy.sparse.linalg.eigen.arpack import eigsh

def renormalize_sparse(A: sp.spmatrix) -> sp.spmatrix:
    """Get (D**-0.5) * A * (D ** -0.5), where D is the diagonalized row sum."""
    A = sp.coo_matrix(A)
    A.eliminate_zeros()
    rowsum = np.array(A.sum(1))
    assert np.all(rowsum >= 0)
    d_inv_sqrt = np.power(rowsum, -0.5).flatten()
    d_inv_sqrt[np.isinf(d_inv_sqrt)] = 0.0
    d_mat_inv_sqrt = sp.diags(d_inv_sqrt)
    return d_mat_inv_sqrt.dot(A).dot(d_mat_inv_sqrt)
    # return A.dot(d_mat_inv_sqrt).transpose().dot(d_mat_inv_sqrt).tocoo()

def chebyshev_polynomials(A: sp.spmatrix, k: int) -> Sequence[sp.spmatrix]:
    """
    Calculate Chebyshev polynomials up to order k.

    Args:
        A: input sparse matrix
        k: order of chebyshev polynomial

    Returns:
        k+1 sparse matrices
    """

    A = renormalize_sparse(A)
    N = A.shape[0]
    laplacian = sp.eye(N) - A
    largest_eigval, _ = eigsh(laplacian, 1, which="LM")
    scaled_laplacian = (2.0 / largest_eigval[0]) * laplacian - sp.eye(N)

    t_k = [sp.eye(N), scaled_laplacian]
    rescaled_laplacian = (2 * scaled_laplacian).tocsr(copy=False)

    for _ in range(2, k + 1):
        t_k.append(rescaled_laplacian.dot(t_k[-1]) - t_k[-2])

    return [t.tocoo(copy=False) for t in t_k]