import jax.numpy as np
import jax.scipy.stats as stats
import jax.scipy.linalg as linalg
import jax
import util
import matplotlib.pyplot as plt
jax.config.update("jax_enable_x64", True)

@jax.jit
def log_prior(theta, sigma0):
    return np.sum(stats.norm.logpdf(theta, scale=sigma0))

@jax.jit
def log_likelihood_per_sample(theta, x, cov):
    return stats.multivariate_normal.logpdf(theta, mean=x, cov=cov)

@jax.jit
def log_likelihood_per_sample_fast(theta, x, chol):
    dim = theta.size
    # const = -0.5 * dim * np.log(2 * np.pi)
    # logdet = -np.sum(np.log(chol.diagonal()))
    z = linalg.solve_triangular(chol, x - theta, lower=True)
    return -0.5 * np.sum(z**2) #+ const + logdet

class GaussModel:
    def __init__(self, dim):
        self.dim = dim
        self.sigma0 = 100
        self.tau0 = 1 / self.sigma0**2
        self.cov = np.eye(dim)
        for i in range(int(self.dim / 2)):
            self.cov = jax.ops.index_update(
                self.cov, jax.ops.index[2*i:2*(i+1), 2*i:2*(i+1)],
                np.array(((1, 0.999), (0.999, 1))) / (i+1)
            )

        self.L = np.linalg.cholesky(self.cov)
        self.true_mean = np.hstack((np.array((0, 3)), np.zeros(dim - 2)))

    def log_prior(self, theta):
        return log_prior(theta, self.sigma0)

    def log_likelihood_per_sample(self, theta, x):
        return log_likelihood_per_sample_fast(theta, x, self.L)

    def generate_data(self, n):
        key = jax.random.PRNGKey(46283648)
        return jax.random.multivariate_normal(key, self.true_mean, self.cov, (n,))

    def compute_posterior_params(self, data):
        n, d = data.shape
        # See Bayesian Data Analysis, section 3.5
        # or https://stats.stackexchange.com/q/28744
        sigma0_mat = np.eye(self.dim) * self.sigma0
        term1 = sigma0_mat @ np.linalg.inv(sigma0_mat + self.cov / n)
        mu_post = term1 @ np.mean(data, axis=0).reshape((-1, 1))
        cov_post = term1 @ self.cov / n
        return (mu_post.reshape(-1,), cov_post)

    def generate_true_posterior(self, samples, data, temp_scale=1, key=None):

        if temp_scale != 1:
            raise Exception("GaussModel does not support sampling tempered posteriors")
        if key is None:
            key = jax.random.PRNGKey(434927)
        mu_post, cov_post = self.compute_posterior_params(data)

        return jax.random.multivariate_normal(key, mu_post, cov_post, (samples,))

    def plot_posterior(self, ax, data):
        mu_post, cov_post = self.compute_posterior_params(data)
        xs = np.linspace(-0.01, 0.01, 1000) + mu_post[0]
        ys = np.linspace(-0.01, 0.01, 1000) + mu_post[1]
        X, Y = np.meshgrid(xs, ys)
        Z = jax.vmap(jax.vmap(lambda x: stats.multivariate_normal.pdf(x, mean=mu_post, cov=cov_post),
            in_axes=1
        ), in_axes=2)(np.stack((X, Y)))
        ax.contour(X, Y, Z)

def get_problem(dim, n):
    model = GaussModel(dim)
    data = model.generate_data(n)
    problem = util.Problem(
        model.log_likelihood_per_sample, model.log_prior,
        data, 1, model.true_mean, model.generate_true_posterior,
        lambda problem, ax: model.plot_posterior(ax, problem.data)
    )
    return problem

if __name__ == "__main__":
    dim = 2
    model = GaussModel(dim)
    data = model.generate_data(100000)
    posterior = model.generate_true_posterior(1000, data)
    fig, ax = plt.subplots()
    model.plot_posterior(ax, data)
    plt.scatter(posterior[:, 0], posterior[:, 1])
    plt.show()
    for i in range(dim):
        print(np.quantile(posterior[:, i], np.array([0.01, 0.99])))

    # x = np.repeat(1, dim)
    # theta = np.repeat(2, dim)
    # print(log_likelihood_per_sample(x, theta, model.cov))
    # L = np.linalg.cholesky(model.cov)
    # print(log_likelihood_per_sample_fast(x, theta, L))

    # log_likelihood_per_sample(np.zeros(dim), np.zeros(dim), np.eye(dim))
    # log_likelihood_per_sample_fast(np.zeros(dim), np.zeros(dim), np.eye(dim))
    # from timeit import timeit
    # print(timeit(lambda: log_likelihood_per_sample(x, theta, model.cov), number=1))
    # print(timeit(lambda: log_likelihood_per_sample_fast(x, theta, L), number=1))


import numpy as np
import matplotlib.pyplot as plt

F = np.array([[0, 0], [0, 1]])
E = np.array([-8, 0])

# Eqn of Parabola is AtFA + EA = 0
# Eqn of tangent must be AtFA1 + 0.5E(A+A1) = 0 (SS1=0)[Given, it passes through [-8, 0]]
	# => GA = 0

Threshold = 0.02 #Define a small threshold to get an approximate solution

l = np.linspace(-10, 10, 10000)
sol1 = 0

for x in l:
	D = np.array([8, x])
	K = np.matmul(D, F)
	L = np.matmul(K, D)
	M = np.matmul(E, D)
	N= np.abs(L + M)
	if N < Threshold:
		sol1 = x

l = np.linspace(10, -10, 10000)
sol2 = 0

for x in l:
	D = np.array([8, x])
	K = np.matmul(D, F)
	L = np.matmul(K, D)
	M = np.matmul(E, D)
	N= np.abs(L + M)
	if N < Threshold:
		sol2 = x

print(sol1)
print(sol2)

A1 = np.array([8, sol1])
A2 = np.array([8, sol2])

Area = 0.5*np.linalg.det([[A1[0], A1[1], 1],[A2[0], A2[1], 1], [2, 0, 1] ])

print(np.abs(Area))

p = np.linspace(0, 15, 10000)
plt.plot(p, np.sqrt(8*p), color = 'blue', label = 'Given Parabola')
plt.plot(p, -np.sqrt(8*p), color = 'blue')

plt.plot([A1[0], -8], [A1[1], 0], color = 'black', label = 'Tangents')
plt.plot([A2[0], -8], [A2[1], 0], color = 'black')

Focus = np.array([2, 0])

plt.plot([A2[0], Focus[0]], [A2[1], Focus[1]], color = 'red')
plt.plot([A1[0], Focus[0]], [A1[1], Focus[1]], color = 'red')
plt.plot([A2[0], A1[0]], [A2[1], A1[1]], color = 'red', label = 'Area Required to Calculate')

plt.text(-8 - 0.5, 0 + 0.5 , "0")
plt.text(A1[0] - 0.5, A1[1] + 0.5 , "A(8, 8)")
plt.text(A2[0] - 0.5, A2[1] + 0.5 , "B(8, -8)")
plt.text(2 - 0.5, 1 + 0.5 , "F(2, 0)")

plt.plot(A1[0], A1[1], "o", color = 'black')
plt.plot(A2[0], A2[1], "o", color = 'black')
plt.plot(-8, 0, "o", color = 'black')
plt.plot(2, 0, "o", color = 'black')

plt.legend()
plt.grid()

plt.savefig('/home/gautham/Desktop/AIML/Fig.png')

plt.show()


from   math import sin, cos, e
import matplotlib.pyplot as plt
import numpy as np

def f(x):
    return x**2-2
def fp(x):
    return 2*x

def iterationMethod(a, b, f, fp, eps_x, eps_y, max_n):
    #третий аргумент return - false , если корень не найден
    n = 0
    for x0 in [a,b]:

        #подбираем lambd
        #lmbd == false => lambda = 1
        #lmbd == true  => lambda = 1/fp(x)
        lmbd = False
        x1 = x0 - f(x0)
        x2 = x1 - f(x1)

        if abs(x2 - x1) > abs(x1 - x0):
            lmbd = True
            if (fp(x1) == 0) or (fp(x0) == 0)  :
                return x1, n, False
            x1 = x0 - f(x0)/fp(x0)
            x2 = x1 - f(x1)/fp(x1)
            if abs(x2 - x1) > abs(x1 - x0):
                return x1, n, False

        while True:
            n += 1

            if not lmbd:
                x1 = x0 - f(x0)
            else:
                x1 = x0 - f(x0)/fp(x0)
            #условия завершения
            if eps_x > 0:
                if abs(x1 - x0) < eps_x:
                    return x1, n, True
            if eps_y > 0:
                if abs(f(x1) - f(x0)) < eps_y:
                    return x1, n, True
            if n >= max_n:
                return x1, n, True
            if  not (a<=x1<=b):
                #если произошел выход за границы
                #обычно срабатывает при отстутсвии корня
                break

            x0 = x1

        #если не найдено корней, то
        return x1, n, False

def generateRootsData(a, b, h, eps_x, eps_y, max_n):
    ah = a
    bh = a + h
    roots_data = []
    step = 1
    while bh <= b:
        x, n, finded = iterationMethod(ah, bh, f, fp, eps_x, eps_y, max_n)
        if finded:
            left_border  = ah
            right_border = bh
            root         = x
            value        = f(x)
            iteration_n  = n
            if n >= max_n:
                err_code = 1
            else:
                err_code = 0
            if not x in [i[2] for i in roots_data]:
                roots_data.append([left_border, right_border, root, value, iteration_n, err_code])

        step += 1
        ah = a + h * (step - 1)
        bh = a + h * step
        if bh > b:
            if ah > b:
                break
            else:
                bh = b
    return roots_data

def inputData():
    inp   = input('Введите интервал поиска [A,B] в формате "A,B":  ')
    a,b   = map(float, inp.split(','))
    inp   = input('Введите шаг h:                                  ')
    h     = float(inp)
    inp   = input('Введите ? по x, если требуется:                 ')
    if inp.strip() == '':
        eps_x = 0
    else:
        eps_x = float(inp)
    inp   = input('Введите ? по y, если требуется:                 ')
    if inp.strip() == '':
        eps_y = 0
    else:
        eps_y = float(inp)
    inp   = input('Введите предельное число итераций n_max >= 100: ')
    max_n = int(inp)
    if not (max_n>=100):
        print('Неверный ввод!')
        return 0
    return a, b, h, eps_x, eps_y, max_n

def printTable(data, max_n):
    # расчет форматированной строки
    maxalen     = len( str(data[-1][0]) + str(data[-1][1]) )
    abrowlen    = maxalen + 5
    iterrowlen  = len('кол-во итераций') + 2
    errrowlen   =  len('код ошибки') + 2
    table_width = (1 + 9 + 1 + abrowlen + 1
                  + 14 + 1 + 15 + 1 + iterrowlen + 1 + errrowlen+1)
    t_row  = ('|{:^9}|{:^'+str(abrowlen)+'}|{:^14}|{:^15}|{:^'+str(iterrowlen)
              +'}|{:^'+str(errrowlen)+'}|')
    t_head = t_row.format('№ корня','[А,B]','корень','f(x)','кол-во итераций',
                          'код ошибки')

    print('-'*table_width)
    print(t_head)
    print('|','-'*(table_width-2),'|', sep='')
    n = 0
    for i in data:
        n += 1
        arg1 = n
        arg2 = ('['+'{:g}'.format(i[0])+','
                +'{:g}'.format(i[1])+']')
        arg3 = '{:g}'.format(i[2])
        arg4 = '{:.0e}'.format(i[3])
        arg5 = i[4]
        arg6 = i[5]
        if arg6 != 0:
            arg3 = arg4 = '-'
        print(t_row.format(arg1, arg2, arg3, arg4, arg5, arg6 ))
    print('-'*table_width)

    print('Коды ошибок: ')
    print('0 - нет ошибки')
    print('1 - достигнуто максимальное количество итераций')

def drawPlot(data, a, b):
    x_f = np.linspace(a,b, 1000)
    y_f = list(map(f, x_f))
    x_roots = []
    y_roots = []
    point_text = []
    for row in range(len(data)):
        if data[row][5] == 0:
            x_roots.append(data[row][2])
            y_roots.append(data[row][3])
            point_text.append(row+1)

    bottom = min(y_f)
    top    = max(y_f)
    if bottom > 0:
        bottom*=0.9
    elif bottom < 0:
        bottom*=1.1
    #else:
    #    bottom = -top * 0.1
    if top > 0:
        top*=1.1
    elif top < 0:
        top*=0.9
    #else:
    #    top = -bottom * 0.1

    ax = plt.subplot()

    plt.axis([a,b, bottom, top])
    plt.title('Finding roots of f(x) with fixed-point iteration method')
    plt.xlabel('x')
    plt.ylabel('f(x)')

    plt.plot(x_f,y_f, '-', color='blue', label='f(x)')
    plt.plot(x_roots, y_roots, 'bo', color='red', label = 'finded roots')

    for i in range(len(x_roots)):
        ax.annotate('#'+str(point_text[i]), (x_roots[i],y_roots[i]))
    plt.legend()

    plt.plot([a,b], [0,0], '-', color='black')
    plt.plot([0,0], [bottom,top], '-', color='black')

    plt.show()

def main():
    while 1:
        print('=== Уточнение корня методом подбора с итерацией ===')
        #ввод данных
        inp_data = inputData()
        if inp_data == 0:
            return
        else:
            a, b, h, eps_x, eps_y, max_n = inp_data

        #генерация и вывод таблицы
        print()
        print('               -  поиск корней  -                  ')
        roots_data = generateRootsData(a, b, h, eps_x, eps_y, max_n)
        if len(roots_data) == 0:
            print('Корней не найдено!')
        else:
            printTable(roots_data, max_n)
        drawPlot(roots_data, a, b)

        #просьба еще одного ввода
        print()
        inp = input('Введите 1, чтобы ввести новые данные: ')
        if inp!='1':
            break
        else:
            print()
            print()

main()

Numerical algorithms/Root finding/Fixed-point iteration method.py

Numerical analysis/Fixed-point iteration method.py


import numpy as np

class Bisection(object):
    def __init__(self, f=None, **extras):
        """
        f : a function f(x) that returns 'y', the function applied to x
        """
        self.f = f

    def solve(self, init_a=None, init_b=None, tol=None, max_it=50, **extras):
        """fast implementation of the bisection method
        init_a : bottom bound of the initial interval
        init_b : top bound of the initial interval
        tol : maximum absolute error after which the method should stop. (e.g. 1e-15)
        max_it : maximum number of iterations after which the method should stop
        """
        i = 0
        c = 0
        a = init_a
        b = init_b
        while i < max_it:
            c = ( (a + b) / 2 )
            if abs(b-c) < tol:
                break
            elif c == 0:
                break
            if np.sign( self.f(b) ) * np.sign( self.f(c) ) <= 0:
                a = c
            else:
                b = c
            i+=1

        return c

    def vsolve(self, init_a=None, init_b=None, tol=None, max_it=50, **extras):
        """verbose implementation of the bisection method
        init_a : bottom bound of the initial interval
        init_b : top bound of the initial interval
        tol : maximum absolute error after which the method should stop. (e.g. 1e-15)
        max_it : maximum number of iterations after which the method should stop
        """

        i = 0
        c = 0
        a = init_a
        b = init_b

        iteration_list = []
        dist_list = []
        estimate_list = []

        while i < max_it:
            co = c
            c = self._half(a,b)
            dist = abs(c-co)

            iteration_list.append(i)
            dist_list.append(dist)
            estimate_list.append(c)

            if abs(b-c) < tol:
                break

            if np.sign( self.f(b) ) * np.sign( self.f(c) ) <= 0:
                a = c
            else:
                b = c

            i+=1

        return iteration_list, estimate_list, dist_list

    def _half(self,a,b):
        return (a + b) / 2

    def __name__(self):
        return "Bisection"

    # def __repr__(self):
        # return "Bisection "
        # raise NotImplementedError

    # def __str__(self):
    #     return "Bisection method"


import scipy.stats

def test_mean(data, prediction):
    try:
        mean = sum(data) / float(len(data))
        assert abs(mean - prediction) < .01
    except AssertionError:
        print('Your calculate_mean function is not working correctly')
        return
    except TypeError:
        print('Your calculate_mean function has not been implemented yet')
        return
    print('Your calculate_mean function is correct')

def test_regression(x, y, prediction_slope, prediction_intercept):
    regression = scipy.stats.linregress(x, y)
    intercept = regression.intercept
    slope = regression.slope

    try:
        assert abs(prediction_intercept - intercept) < .01
        assert abs(prediction_slope - slope) < .01
    except AssertionError:
        print('Your calculate_regression_coeff function is not working correctly')
        return
    except TypeError:
        print('Your calculate_regression_coeff function has not been implemented yet')
        return
    print('Your calculate_regression_coeff function is correct')

def test_heatmap_read(df):
    '''Test that the student read in the dataframe correctly'''
    try:
        assert len(df) == 30
    except AssertionError:
        print("Your dataframe isn't the correct length. Are you sure you read the right file?")
        return
    except TypeError:
        print('Your create_dataframe function has not been implemented yet')
        return
    try:
        assert len(df.columns) == 6
    except AssertionError:
        print("Your dataframe doesn't have the correct number of columns, are you sure you read the right file?")
        return

    print('You successfully read in your dataframe')

def test_heatmap_melt(df):
    '''Test that the heatmap dataframe was melted correctly'''
    try:
        assert len(df.columns) == 3
    except AssertionError:
        print("Your dataframe doesn't have the correct number of columns.")
        print("The dataframe should have a column for genes, case/control status, and expression")
        print("Printing the first few rows of your dataframe with df.head() might help find the bug")
        return
    except AttributeError:
        print('Your melt_dataframe function has not been implemented yet')
        return

    try:
        assert len(df) == 150
    except AssertionError:
        print("Your dataframe doessn't have the correct number of rows.")
        print("The dataframe should have a column for genes, case/control status, and expression")
        print("Printing the first few rows of your dataframe with df.head() might help find the bug")
        return

    print('You successfully reformated your dataframe')

def test_box_read(df):
    try:
        assert len(df) == 50
    except AssertionError:
        print("Your dataframe doesn't have the correct number of rows, are you sure you read the correct file?")
        return
    except TypeError:
        print("Your read_data function isn't impemented yet")
        return

    try:
        assert len(df.columns) == 2
    except AssertionError:
        print("Your dataframe doesn't have the correct number of columns, are you sure you read it as a tab separated file?")
        return

    print('You successfully read in the dataset')

def test_box_melt(df):
    try:
        assert len(df) == 100
    except AssertionError:
        print("Your dataframe doesn't have the correct number of rows.")
        print("Looking back at the reformattingg code in the previous question might help.")
        return
    except TypeError:
        print("Your melt function isn't impemented yet")
        return

    print('You successfully reformatted the dataset')


import numpy as np
a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print(a>3) #Where is A>3?

'''
[[False False False]
 [ True  True  True]
 [ True  True  True]]

gives the above.
So in 0th list, none are true. Then you have 1st list, 0th is true. 1st list 1th is true. 1st list 2nd is true
so you have 1-0, 1-1, 1-2, where 1st # is the list # and 2nd # is the index in that list
In the 2nd list (3rd one), 0th is true, 1st etc.

'''
print(np.nonzero(a>3))
'''
(array([1, 1, 1, 2, 2, 2]), array([0, 1, 2, 0, 1, 2]))
gives above. So the first array is the list #, and 2nd array is the index within that list
so list 1  number 0, list 1 number 1, list 1 number 2
list 2 number 0, list 2 number 1, list 2 number 2

'''


import numpy as np

def Maindiagonal(n, r):
    """

    :param n: 矩阵的维度
    :param r: 对角线元素
    :return: 一个对角矩阵
    """
    a = np.zeros((n, n))
    for i in range(n):
        a[i][i] = r
    return a

# r1:main r2:上负对角线元素　r3:下负对角线元素
def tri_diagonal(n, r1, r2, r3):
    """

    :param n: 矩阵的维度
    :param r1: 主对角元素
    :param r2: 次上对角元素
    :param r3: 次下对角元素
    :return: 对称正定的矩阵(或者说是三对角矩阵)
    """
    a = np.zeros((n, n))
    for i in range(n):
        if i == 0:
            a[i][i] = r1
            a[i][i + 1] = r2
        elif i == n - 1:
            a[i][i] = r1
            a[i][i - 1] = r3
        else:
            a[i][i] = r1
            a[i][i + 1] = r2
            a[i][i - 1] = r3
    return a

def M_tri_diagonal(nx, ny, b1, b2, b3):
    """

    :param nx:
    :param ny:
    :param b1:正对角块矩阵
    :param b2: 次上对角块矩阵
    :param b3: 次下对角块矩阵
    :return: 一个五带的对称正定矩阵
    """
    N = nx * ny
    a = np.zeros((N, N))
    for i in range(nx):
        if i == 0:
            a[0:ny, 0:ny] = b1
            a[0:ny, ny:2 * ny] = b2
        elif i == nx - 1:
            a[N - ny:N, N - ny:N] = b1
            a[N - ny:N, N - 2 * ny:N - ny] = b3
        else:
            a[i * ny:(i + 1) * ny, i * ny:(i + 1) * ny] = b1
            a[i * ny:(i + 1) * ny, (i + 1) * ny:(i + 2) * ny] = b2
            a[i * ny:(i + 1) * ny, (i - 1) * ny:i * ny] = b3
    return a

def five_diagonal(nx, ny, r1, r2, r3, r4, r5):
    """
    返回一个具有五带非零元素的对称正定矩阵
    :param nx: x轴的节点数（看情况可以是内节点和外界点数）
    :param ny: y轴的节点数
    :param r1: 主对角
    :param r2: 上次对角
    :param r3: 下次对角
    :param r4: 上次角的右边非零元素
    :param r5: 下次对角左边非零元素
    :return: 一个五带的对称正定矩阵
    """
    d = tri_diagonal(ny, r1, r2, r3)  # 主对角块矩阵
    b = Maindiagonal(ny, r4)  # 上对角块矩阵
    c = Maindiagonal(ny, r5)  # 下对角块矩阵
    a = M_tri_diagonal(nx, ny, d, b, c)
    return a

def csrmatrix(A, data, indices, indptr):
    k = 0
    nr = A.shape[0]
    nc = A.shape[1]
    for i in range(nr):
        for j in range(nc):
            if A[i][j] != 0:
                data[k] = A[i][j]
                indices.append(j)
                k += 1
        indptr.append(k)

# 写一些测试内容，在次判断下导入该包的文件不会输出这些内容
# 也可以单独写一个函数来写测试内容，然后在这里调用它,比如def main():
if __name__ == "__main__":
    print("test")
    # main()


from math import e, sin, cos
import pandas as pd
from sympy import Symbol, integrate, lambdify

x = Symbol('x')

print("Численные методы решения задачи Коши для обыкновенного дифференциального уравнения\nВариант 5\n")
print('y´(x)= - y(x) + sin(x), y(0)=1')
dy = lambda x, y: - y + sin(x)
y = lambda x: 1 / 2 * (3 * e ** (-x) - cos(x) + sin(x))

def series(x_):
    return 1 - (x_ - x0) + (x_ - x0) ** 2 - 1 / 3 * (x_ - x0) ** 3 + 1 / 24 * (x_ - x0) ** 4 - 1 / 120 * (x_ - x0) ** 5

def def_int(func, a, b):
    int_ = lambdify(x, integrate(func, x))
    return int_(b) - int_(a)

def kf(f_, arr, A, B):
    x_ = list(arr['x'])
    y_ = list(arr['T_n(x)'])
    w = (x - x_[0]) * (x - x_[1]) * (x - x_[2]) * (x - x_[3]) * (x - x_[4])
    d_w = lambda x: (5 * x ** 4 -
                     4 * x ** 3 * (sum(x_)) +
                     3 * x ** 2 * (x_[0] * x_[1] + x_[0] * x_[2] + x_[0] * x_[3] + x_[0] * x_[4] + x_[1] * x_[2] +
                                   x_[1] * x_[3] + x_[1] * x_[4] + x_[2] * x_[3] + x_[2] * x_[4] + x_[3] * x_[4]) -
                     2 * x ** 1 * (x_[0] * x_[1] * x_[2] + x_[0] * x_[1] * x_[3] + x_[0] * x_[1] * x_[4] +
                                   x_[0] * x_[2] * x_[3] + x_[0] * x_[2] * x_[4] + x_[0] * x_[3] * x_[4] +
                                   x_[1] * x_[2] * x_[3] + x_[1] * x_[2] * x_[4] + x_[1] * x_[3] * x_[4] +
                                   x_[2] * x_[3] * x_[4]) +
                     1 * x ** 0 * (
                             x_[0] * x_[1] * x_[2] * x_[3] + x_[0] * x_[1] * x_[2] * x_[4] + x_[0] * x_[1] * x_[4] *
                             x_[3] +
                             x_[0] * x_[4] * x_[2] * x_[3] + x_[4] * x_[1] * x_[2] * x_[3])
                     )

    res = sum(def_int(w / (x - x_[i]) / d_w(x_[i]), A, B) * f_(x_[i], y_[i]) for i in range(5))
    return y_[4] + res

def taylor():
    global df
    df = pd.DataFrame(
        [(x0 + k * h, series(x0 + k * h), abs(series(x0 + k * h) - y(x0 + k * h))) for k in
         range(-2, n + 1)]).rename(columns={0: 'x', 1: 'T_n(x)', 2: '|y - T_n(x)|'}, axis=None)
    return

def adams():
    global df
    for k in range(3, n + 1):
        xi = float(df.tail(1)['x'])
        d = kf(dy, df[-5:], xi, xi + h)
        df = df.append({'x': xi + h, 'T_n(x)': d}, ignore_index=True)

    return

def runge_kutta(xi, yi):
    global df
    for k in range(n):
        k1 = h * dy(xi, yi)
        k2 = h * dy(xi + h / 2, yi + k1 / 2)
        k3 = h * dy(xi + h / 2, yi + k2 / 2)
        k4 = h * dy(xi + h, yi + k3)
        xi += h
        yi += 1 / 6 * (k1 + 2 * k2 + 2 * k3 + k4)
        df = df.append({'x': xi, 'y': yi}, ignore_index=True)
        # print(xi, yi)
    return

def euler(xi, yi):
    global df
    for k in range(n):
        yi += h * dy(xi, yi)
        xi += h
        df = df.append({'x': xi, 'y': yi}, ignore_index=True)
        # print(xi, yi)
    return

def euler_mod(xi, yi):
    global df
    for k in range(n):
        yi_2 = yi + h / 2 * dy(xi, yi)
        yi += h * dy(xi + h / 2, yi_2)
        xi += h
        df = df.append({'x': xi, 'y': yi}, ignore_index=True)
    return

def euler_cauchy(xi, yi):
    global df
    for k in range(n):
        t = yi + h * dy(xi, yi)
        yi += h / 2 * (dy(xi, yi) + dy(xi + h, t))
        xi += h
        df = df.append({'x': xi, 'y': yi}, ignore_index=True)
    return

print('h = 0.1\nN = 10')
h = 0.1
n = 10
x0 = 0
y0 = 1

# Точное решение
solution = pd.DataFrame([(x0 + k * h - 2, y(x0 + k * h)) for k in range(-2, n + 1)])
solution = solution.rename(columns={0: 'x', 1: 'y'})
solution.index -= 2
print("\nТаблица значений точного решения")
print(solution)

# Ряд Тейлора
df = pd.DataFrame(columns=['x', 'y'])
taylor()
df.index -= 2
print('\nМетод разложения в р. Тейлора:')
print(df[:5])

# Метод Адамса
df = df[:5]
df = df.drop('|y - T_n(x)|', axis=1)
adams()
df = df.rename(columns={'T_n(x)': 'y'})
df.index -= 2
print('\nЭкстраполяционный метод Адамса:')
print(df[5:])
print('Абс. факт. погрешность метода Адамса для y(x_n):', abs(list(df['y'])[-1] - list(solution['y'])[-1]))
df = df.iloc[0:0]

# Метод Рунге-Кутты
runge_kutta(0, 1)
print('\nМетод Рунге-Кутты:')
df.index += 1
print(df[:n])
print('Абс. факт. погрешность метода Рунге-Кутты для y(x_n):', abs(list(df['y'])[-1] - list(solution['y'])[-1]))
df = df.iloc[0:0]

# Метод Эйлера
euler(0, 1)
print('\nМетод Эйлера:')
df.index += 1
print(df)
print('Абс. факт. погрешность метода Эйлера для y(x_n):', abs(list(df['y'])[-1] - list(solution['y'])[-1]))
df = df.iloc[0:0]

# Модифицированный метод Эйлера
euler_mod(0, 1)
print('\nМодифицированный метод Эйлера:')
df.index += 1
print(df)
print('Абс. факт. погрешность мод. метода Эйлера для y(x_n):', abs(list(df['y'])[-1] - list(solution['y'])[-1]))
df = df.iloc[0:0]

# Метод Эйлера-Коши
euler_cauchy(0, 1)
print('\nМетод Эйлера-Коши:')
df.index += 1
print(df)
print('Абс. факт. погрешность метода Эйлера-Коши для y(x_n):', abs(list(df['y'])[-1] - list(solution['y'])[-1]))
df = df.iloc[0:0]


import numpy as np
import matplotlib.pyplot as plt

N = 50                                # Number of points in each direction
x_start, x_end = -2.0, 2.0            # x-direction boundaries
y_start, y_end = -1.0, 1.0            # y-direction boundaries
x = np.linspace(x_start, x_end, N)    # computes a 1D-array for x
y = np.linspace(y_start, y_end, N)    # computes a 1D-array for y
X, Y = np.meshgrid(x, y)

kappa = 1.0                           # strength of the doublet
x_doublet, y_doublet = 0.0, 0.0       # location of the doublet

u_inf = 1.0

def get_velocity_doublet(strength, xd, yd, X, Y):

    u = - strength / (2 * np.pi) * ((X - xd)**2 - (Y - yd)
                                    ** 2) / ((X - xd)**2 + (Y - yd)**2)**2
    v = - strength / (2 * np.pi) * 2 * (X - xd) * \
        (Y - yd) / ((X - xd)**2 + (Y - yd)**2)**2

    return u, v

def get_stream_function_doublet(strength, xd, yd, X, Y):

    psi = - strength / (2 * np.pi) * (Y - yd) / ((X - xd)**2 + (Y - yd)**2)

    return psi

# computes the velocity field on the mesh grid
u_doublet, v_doublet = get_velocity_doublet(kappa, x_doublet, y_doublet, X, Y)

# computes the stream-function on the mesh grid
psi_doublet = get_stream_function_doublet(kappa, x_doublet, y_doublet, X, Y)

# freestream velocity components
u_freestream = u_inf * np.ones((N, N), dtype=float)
v_freestream = np.zeros((N, N), dtype=float)

# stream-function of the freestream flow
psi_freestream = u_inf * Y

# superposition of the doublet on the freestream flow
u = u_freestream + u_doublet
v = v_freestream + v_doublet
psi = psi_freestream + psi_doublet

# plots the streamlines
size = 10
plt.figure(figsize=(size, (y_end - y_start) / (x_end - x_start) * size))
plt.xlabel('x', fontsize=16)
plt.ylabel('y', fontsize=16)
plt.xlim(x_start, x_end)
plt.ylim(y_start, y_end)
plt.streamplot(X, Y, u, v, density=2, linewidth=1,
               arrowsize=1, arrowstyle='->')
plt.scatter(x_doublet, y_doublet, color='#CD2305', s=80, marker='o')

# calculates the cylinder radius and adds it to the figure
R = np.sqrt(kappa / (2 * np.pi * u_inf))
circle = plt.Circle((0, 0), radius=R, color='#CD2305', alpha=0.5)
plt.gca().add_patch(circle)

# calculates the stagnation points and adds it to the figure
x_stagn1, y_stagn1 = +np.sqrt(kappa / (2 * np.pi * u_inf)), 0
x_stagn2, y_stagn2 = -np.sqrt(kappa / (2 * np.pi * u_inf)), 0
plt.scatter([x_stagn1, x_stagn2], [y_stagn1, y_stagn2],
            color='g', s=80, marker='o')

plt.show()

gamma = 4 * np.pi * u_inf * R

x_vortex, y_vortex = 0.0, 0.0    # location of the vortex

def get_velocity_vortex(strength, xv, yv, X, Y):

    u = + strength / (2 * np.pi) * (Y - yv) / ((X - xv)**2 + (Y - yv)**2)
    v = - strength / (2 * np.pi) * (X - xv) / ((X - xv)**2 + (Y - yv)**2)
    return u, v

def get_stream_function_vortex(strength, xv, yv, X, Y):

    psi = strength / (4 * np.pi) * np.log((X - xv)**2 + (Y - yv)**2)

    return psi

# computes the velocity field on the mesh grid
u_vortex, v_vortex = get_velocity_vortex(gamma, x_vortex, y_vortex, X, Y)

# computes the stream-function on the mesh grid
psi_vortex = get_stream_function_vortex(gamma, x_vortex, y_vortex, X, Y)

# superposition of the doublet and the vortex on the freestream flow
u = u_freestream + u_doublet + u_vortex
v = v_freestream + v_doublet + v_vortex
psi = psi_freestream + psi_doublet + psi_vortex

# calculates cylinder radius
R = np.sqrt(kappa / (2 * np.pi * u_inf))

# calculates the stagnation points
x_stagn1, y_stagn1 = + \
    np.sqrt(R**2 - (gamma / (4 * np.pi * u_inf))**2), - \
    gamma / (4 * np.pi * u_inf)
x_stagn2, y_stagn2 = - \
    np.sqrt(R**2 - (gamma / (4 * np.pi * u_inf))**2), - \
    gamma / (4 * np.pi * u_inf)

# plots the streamlines
size = 10
plt.figure(figsize=(size, (y_end - y_start) / (x_end - x_start) * size))
plt.xlabel('x', fontsize=16)
plt.ylabel('y', fontsize=16)
plt.xlim(x_start, x_end)
plt.ylim(y_start, y_end)
plt.streamplot(X, Y, u, v, density=2, linewidth=1,
               arrowsize=1.5, arrowstyle='->')
circle = plt.Circle((0, 0), radius=R, color='#CD2305', alpha=0.5)
plt.gca().add_patch(circle)
plt.scatter(x_vortex, y_vortex, color='#CD2305', s=80, marker='o')
plt.scatter([x_stagn1, x_stagn2], [y_stagn1, y_stagn2],
            color='g', s=80, marker='o')

plt.show()

# calculates the surface tangential velocity on the cylinder
theta = np.linspace(0, 2 * np.pi, 100)
u_theta = -2 * u_inf * np.sin(theta) - gamma / (2 * np.pi * R)

# computes the surface pressure coefficient
cp = 1.0 - (u_theta / u_inf)**2

# if there was no vortex
u_theta_no_vortex = -2 * u_inf * np.sin(theta)
cp_no_vortex = 1.0 - (u_theta_no_vortex / u_inf)**2

# plots the surface pressure coefficient
size = 6
plt.figure(figsize=(size, size))
plt.grid(True)
plt.xlabel(r'$\theta$', fontsize=18)
plt.ylabel(r'$C_p$', fontsize=18)
plt.xlim(theta.min(), theta.max())
plt.plot(theta, cp, color='#CD2305', linewidth=2, linestyle='-')
plt.plot(theta, cp_no_vortex, color='g', linewidth=2, linestyle='-')
plt.legend(['with vortex', 'without vortex'], loc='best', prop={'size': 16})

plt.show()


import mpmath
from mpsci.distributions import benktander2

def test_pdf():
    with mpmath.workdps(50):
        x = mpmath.mpf('1.5')
        a = 2
        b = mpmath.mpf('0.75')
        p = benktander2.pdf(x, a, b)
        # Expected value computed with Wolfram Alpha:
        #    PDF[BenktanderWeibullDistribution[2, 3/4], 3/2]
        valstr = '0.6913485277470671248347955016586714957100372820095067311673'
        expected = mpmath.mpf(valstr)
        assert mpmath.almosteq(p, expected)

def test_logpdf():
    with mpmath.workdps(50):
        x = mpmath.mpf('1.5')
        a = 2
        b = mpmath.mpf('0.75')
        p = benktander2.logpdf(x, a, b)
        # Expected value computed with Wolfram Alpha:
        #    log(PDF[BenktanderWeibullDistribution[2, 3/4], 3/2])
        valstr = '-0.369111200683201817345059066451331575064497370791420217397'
        expected = mpmath.mpf(valstr)
        assert mpmath.almosteq(p, expected)

def test_cdf_invcdf():
    with mpmath.workdps(50):
        x = mpmath.mpf('1.5')
        a = 2
        b = mpmath.mpf('0.75')
        p = benktander2.cdf(x, a, b)
        # Expected value computed with Wolfram Alpha:
        #    CDF[BenktanderWeibullDistribution[2, 3/4], 3/2]
        valstr = '0.6497498357448767493508965922137966312235765166018499603595'
        expected = mpmath.mpf(valstr)
        assert mpmath.almosteq(p, expected)
        x1 = benktander2.invcdf(expected, a, b)
        assert mpmath.almosteq(x1, x)

def test_sf_invsf():
    with mpmath.workdps(50):
        x = mpmath.mpf('1.5')
        a = 2
        b = mpmath.mpf('0.75')
        p = benktander2.sf(x, a, b)
        # Expected value computed with Wolfram Alpha:
        #    SurvivalFunction[BenktanderWeibullDistribution[2, 3/4], 3/2]
        valstr = '0.3502501642551232506491034077862033687764234833981500396405'
        expected = mpmath.mpf(valstr)
        assert mpmath.almosteq(p, expected)
        x1 = benktander2.invsf(expected, a, b)
        assert mpmath.almosteq(x1, x)

def test_mean():
    with mpmath.workdps(50):
        a = 2
        b = mpmath.mpf('0.25')
        m = benktander2.mean(a, b)
        assert mpmath.almosteq(m, mpmath.mpf('1.5'))

def test_var():
    with mpmath.workdps(50):
        a = 2
        b = mpmath.mpf('0.25')
        m = benktander2.var(a, b)
        # Expected value computed with Wolfram Alpha:
        #    Var[BenktanderWeibullDistribution[2, 1/4]]
        expected = mpmath.mpf('251/512')
        assert mpmath.almosteq(m, expected)


import numpy as np
from numpy.fft import *

x = [1, 2, 3, 4]
x = np.array(x)

print("\n---x")
print(x)
print("\n---fft([1, 2, 3, 4])")
print(fft([1, 2, 3, 4]))
print("\n---fft([4, 3, 2, 1])")
print(fft([4, 3, 2, 1]))

x = [
    [1, 2, 3, 4, 5],
    [6, 7, 8, 9, 10],
    [11, 12, 13, 14, 15],
    [16, 17, 18, 19, 20],
]

x = np.array(x)

print("\n---x")
print(x)
print("\n---fftshift(x, axes=0)")
print(fftshift(x, axes=0))
print("\n---fftshift(x, axes=1)")
print(fftshift(x, axes=1))

print("\n---x")
print(x)
print("\n---ifftshift(x, axes=0)")
print(ifftshift(x, axes=0))
print("\n---ifftshift(x, axes=1)")
print(ifftshift(x, axes=1))

y0 = fft(x, axis=0)
y1 = fft(x, axis=1)

print("\n---fft(x, axis=0)")
print(y0)
print("\n---fft(x, axis=1)")
print(y1)

ys00 = fft(fftshift(x, axes=0), axis=0)
ys11 = fft(fftshift(x, axes=1), axis=1)

print("\n---fft(fftshift(x, axes=0), axis=0)")
print(ys00)
print("\n---fft(fftshift(x, axes=1), axis=1)")
print(ys11)

ys000 = fftshift(fft(fftshift(x, axes=0), axis=0), axes=0)
ys111 = fftshift(fft(fftshift(x, axes=1), axis=1), axes=1)

print("\n---fftshift(fft(fftshift(x, axes=0), axis=0), axes=0)")
print(ys000)
print("\n---fftshift(fft(fftshift(x, axes=1), axis=1), axes=1)")
print(ys111)

print("-------------------------------------")

x = [1, 2, 3, 4]
x = np.array(x)

y = fft(x)

print("---x")
print(x)

print("---fft(x)")
print(y)

yy = fftshift(fft(fftshift(x)))

print("---x")
print(x)

print("---fftshift(fft(fftshift(x)))")
print(yy)

x = ifft(y)
print("---ifft(fft(x))")
print(x)

x = ifft(yy)
print("---ifft(yy)")
print(x)

x = ifft(fftshift(yy))
print("---ifft(fftshift(yy))")
print(x)

x = fftshift(ifft(yy))
print("---fftshift(ifft(yy))")
print(x)

x = ifftshift(ifft(ifftshift(yy)))
print("---ifftshift(ifft(ifftshift(yy)))")
print(x)

x = fftshift(ifft(fftshift(yy)))
print("---fftshift(ifft(fftshift(yy)))")
print(x)

x = ifftshift(ifft(fftshift(yy)))
print("---ifftshift(ifft(fftshift(yy)))")
print(x)

x = fftshift(ifft(ifftshift(yy)))
print("---fftshift(ifft(ifftshift(yy)))")
print(x)


import numpy as np
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
from sklearn import metrics

import matplotlib.pyplot as plt

# loading iris dataset
iris = load_iris()

# printing features and labels
print("features names: ", iris.feature_names)
print("iris types names: ", iris.target_names)

# storing features and labels
iris_X = iris.data
iris_y = iris.target

# printing number of samples
print("shape of data: ", iris_X.shape)

# spitting train set and test set
X_train, X_test, y_train, y_test = train_test_split(
    iris_X, iris_y, test_size=0.2, random_state=7)

# finding optimum k for our algorithm
k_range = range(1, 20)
scores = dict()
scores_list = list()

for k in k_range:
    knn = KNeighborsClassifier(n_neighbors=k)
    knn.fit(X_train, y_train)
    y_pred = knn.predict(X_test)
    scores[k] = metrics.accuracy_score(y_test, y_pred)
    scores_list.append(metrics.accuracy_score(y_test, y_pred))

# plotting the result
plt.plot(k_range, scores_list)
plt.xlabel("Value of K")
plt.ylabel("Accuracy")

# -------- finally -------- #
# getting optimum k
knn = KNeighborsClassifier(n_neighbors=np.argmax(scores_list))

# fitting the whole dataset
knn.fit(iris_X, iris_y)

# names of iris types
types = {i: iris.target_names[i] for i in range(len(iris.target_names))}

# creating sample validation set
X_val = [[7, 5, 7, 5], [4, 4, 3, 3]]
y_val = knn .predict(X_val)

for i in range(len(X_val)):
    print(types[y_val[i]])

plt.show()


import math
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np

# the following code is provided and doesn't need to be changed.

def selection(population,number_of_parameters):
    '''
    Rank the individuals of the population
    '''
    # we implement rank selection here, i.e. the individuals with the highest fitness go to the next stage
    # in the current implementation that simply means that we have to sort the population according to fitness
    #(the last column)

    population = population[population[:,number_of_parameters].argsort()] # this sorts the array with the individuals with the lowest fitness at the top (remember
    # we want to minimize our function)

    return population

def evaluateFitness(population,capacity,number_of_parameters):
    '''
    Evaluate the fitness of  all individuals
    '''
    for i in range(capacity):
        #print('evaluation:',i)
        # take the parameters of the i-th individual and evaluate the fitness, save the fitness value in the last column
        population[i,number_of_parameters] = fitness_function(population[i,0:number_of_parameters])

    return population

def visualize(population,size):
    '''
    Visualize each individual of the population in a 3D plot.
    The individual with the best fitness is marked with a red cross
    '''
    # Note: only works for two parameters (but that's all we need for this exercise)
    fig = plt.figure()
    ax3d = fig.add_subplot(111,projection='3d')
    ax3d.scatter(population[1:size,0],population[1:size,1],population[1:size,2],c='k',marker='o') # plot all individuals in black with a 'o' marker
    ax3d.scatter(population[0,0],population[0,1],population[0,2],c='r',marker='x') # plot the best individual in red with a 'x' marker
    plt.show()

def fitness_function(params):# the function to optimize
    """
    Computes the "fitness" of a set of parameters. The lower the fitness, the better.
    """
    x = params[0]
    y = params[1]
    fitness = (3*(x**2))+(4*(y**2)) # here you should replace None with the code for the function of x and y as above
    return fitness

###### don't change the code below

assert fitness_function([3,4]) == 91, 'please check your implementation'
assert fitness_function([3,2]) == 43, 'please check your implementation'
assert fitness_function([5,23]) == 2191, 'please check your implementation'

def mutation(population, size, r_mutation, p_mutation, s_mutation, number_of_parameters):
    '''
    mutation - mutate a random subset of the population
    Parameters:
    population - the population from the current generation
    (We simply represent the parameters as a numpy array, and initialize it with random numbers
    the first size rows represent the actual population, the rest gets filled during mutation and crossover
    the first number_of_parameters columns contain the parameters, the last column contains the fitness value)
    size - the size of the population
    r_mutation - the percentage of individuals from the population that undergo mutation
    p_mutation - the probability of a mutation of a single parameter of an individual
    s_mutation - the strength of the mutation
    number_of_parameters - the number of parameters each individual has
    '''
    # choose a random subset of the population which will undergo mutation
    cutoff = int(size*r_mutation) # this is the number of individuals that will undergo mutation
    indices = np.arange(size)

    np.random.shuffle(indices)
    mutation_set = indices[:cutoff] # these are the indices of the randomly chosen individuals that will undergo
                                    # mutation

    inc = 0
    for i in mutation_set: # loop through all individuals that undergo mutation

        for j in range(number_of_parameters): # loop through all parameters of each individual
            p = np.random.rand() # integer in interval 0,1
            if p <= p_mutation: # if integer > p_mutation perform mutation
                r = (1*s_mutation) * np.random.random_sample() - (0.5*s_mutation) # generate number in range given
                population[i,j] = population[i,j] + r # parameter value + r
                population[size+inc,1] = r # store mutated parameter into population
        population[size+inc,0] = population[size+inc,1] # store mutated individual into population
        inc += 1

    return population

###### don't change the code below
population = np.random.random_sample((25,3))
pop = np.array(population)
mutation_population = mutation(population,10,1.0,1.0,1.0,2)

assert mutation_population[10,0] != pop[10,0], 'please check your implementation'
assert mutation_population[10,1] != pop[10,1], 'please check your implementation'
assert mutation_population[11,0] != pop[11,0], 'please check your implementation'
assert mutation_population[11,1] != pop[11,1], 'please check your implementation'
assert mutation_population[12,0] != pop[12,0], 'please check your implementation'
assert mutation_population[12,1] != pop[12,1], 'please check your implementation'
assert mutation_population[13,0] != pop[13,0], 'please check your implementation'
assert mutation_population[13,1] != pop[13,1], 'please check your implementation'
assert mutation_population[14,0] != pop[14,0], 'please check your implementation'
assert mutation_population[14,1] != pop[14,1], 'please check your implementation'

def crossover(population,size,r_crossover,r_mutation,number_of_parameters):
    '''
     crossover - Choose a random subset of the population, select parent pairs and produce offspring
    Parameters:
    population - the population from the current generation
    (We simply represent the parameters as a numpy array, and initialize it with random numbers
    the first size rows represent the actual population, the rest gets filled during mutation and crossover
    the first number_of_parameters columns contain the parameters, the last column contains the fitness value)
    size - the size of the population)
    r_crossover - the percentage of individuals from the population that serve as parents for crossover
    r_mutation - the percentage of individuals from the population that undergo mutation (needed in order
    to correctly store the newly produced offspring!)
    number_of_parameters - the number of parameters each individual has
    '''
    # At the moment, when we do the crossover, the population is already sorted according to fitness values!
    cutoff = int(size*r_crossover) # this is the number of individuals that will undergo crossover
    crossover_set = np.arange(cutoff) # these are the indices of the self.r_crossover % individuals that will undergo crossover
    a = int((size * r_mutation) + size) # continuation from mutated individuals

    n = 0
    while n<cutoff:
        individual_a = np.random.choice(crossover_set) # randomly choose the first individual
        crossover_set = [x for x in crossover_set if x not in [individual_a]] # remove the individual from the set
        individual_b = np.random.choice(crossover_set) # randomly choose the second individual from the remaining set
        crossover_set = [x for x in crossover_set if x not in [individual_b]] # remove the individual from the set
        # perform the actual crossover
        # here you should place your code for task 3);
        # the comments in the following lines give you a hint of what you are supposed to do
        for j in range(number_of_parameters):
            #print(j)
            r = np.random.rand()
            if r < 0.5:
                population[a,j] = population[individual_a,j]
            else:
                population[a,j] = population[individual_b,j]
        n = n+2# increase counter by 2, since we have chosen 2 individuals
        a = a + 1
    return population

###### don't change the code below
population = np.random.random_sample((25,3))
pop = np.array(population)
crossover_population = crossover(population,10,1.0,1.0,2)

assert crossover_population[20,0] != pop[20,0], 'please check your implementation'
assert crossover_population[20,1] != pop[20,1], 'please check your implementation'
assert crossover_population[21,0] != pop[21,0], 'please check your implementation'
assert crossover_population[21,1] != pop[21,1], 'please check your implementation'
assert crossover_population[22,0] != pop[22,0], 'please check your implementation'
assert crossover_population[22,1] != pop[22,1], 'please check your implementation'
assert crossover_population[23,0] != pop[23,0], 'please check your implementation'
assert crossover_population[23,1] != pop[23,1], 'please check your implementation'

def evolve(population,size,r_mutation,p_mutation,s_mutation,r_crossover,capacity,number_of_parameters,number_of_generations):
    '''
    evolve - evolves the genetic algorithm for the specified number of generations
    Parameters:
    population - the population from the current generation
    size - the size of the population
    r_mutation - the percentage of individuals from the population that undergo mutation
    p_mutation - the probability of a mutation of a single parameter of an individual
    s_mutation - the strength of the mutation
    r_crossover - the percentage of individuals from the population that serve as parents for the crossover
    capacity - the overall size of the population array (includes the actual population, the newly mutated individuals
    and the newly produced offspring)
    number_of_parameters - the number of parameters each individual has
    number_of_generations - the number of generations the genetic algorithm will be evolved
    '''

    for i in range(number_of_generations):
        print(i) # print the current generation number
        # here you should place your code for task 4)
        # decide in which order the functions have to be called
        # call them and give them the correct parameters as arguments
        evaluateFitness(population, capacity, number_of_parameters)
        population = selection(population, number_of_parameters)
        crossover(population,size,r_crossover,r_mutation,number_of_parameters )
        mutation(population, size, r_mutation, p_mutation, s_mutation, number_of_parameters)

    #visualize(population,size)
    return population

size = 100 # the size of the population
number_of_parameters = 2 # the number of parameters the function takes
number_of_generations = 20 # number of generations that are executed
p_mutation  = 0.5 # the probability of a mutation
r_mutation  = 0.2 # the percentage of individuals that undergo mutation
s_mutation  = 1.25 # the mutation strength
r_crossover = 0.4 # the percentage of individuals that undergo crossover

capacity = size + int(size*r_mutation) + int(size*r_crossover/2.0) # this is the size of the population after crossover and selection
print("capactiy",capacity)
# We simply represent the parameters as a numpy array, and initialize it with random numbers
# the first size rows represent the actual population, the rest gets filled during mutation and crossover
# the first number_of_parameters columns contain the parameters, the last column contains the fitness value
population = np.random.random_sample((capacity,number_of_parameters+1))

final_population = evolve(population,size,r_mutation,p_mutation,s_mutation,r_crossover,capacity,number_of_parameters,number_of_generations)

###### don't change the code below

print(final_population[0,2])
assert final_population[0,2] < 0.001, 'please check your implementation'
assert final_population[1,2] < 0.001, 'please check your implementation'
assert final_population[2,2] < 0.001, 'please check your implementation'
assert final_population[3,2] < 0.001, 'please check your implementation'
assert final_population[4,2] < 0.001, 'please check your implementation'


# load required library
import matplotlib.pyplot as plt
import numpy as np
from sklearn.datasets import load_iris
import scipy.optimize as opt

x, y = load_iris(return_X_y=True)
x = x[:100, :2]  # class 0 and 1 balanced
y = y[:100]

def draw_data(x, y):
    #########################################################################
    # Full Mark: 1                                                          #
    # TODO:                                                                 #
    # 1. make a scatter plot of the raw data                                #
    # 2. set title for the plot                                             #
    # 3. set label for x,y axis                                             #
    # Note, this scatter plot has two different type of points              #
    #########################################################################
    plt.title("Logistic Regression")
    plt.xlabel("x")
    plt.ylabel("y")
    pos = np.where(y == 0)
    neg = np.where(y == 1)
    plt.scatter(x[pos, 0], x[pos, 1], marker='x', color='r', label='class0')
    plt.scatter(x[neg, 0], x[neg, 1], marker='o', color='b', label='class1')
    plt.legend()
    #########################################################################
    #                       END OF YOUR CODE                                #
    #########################################################################

    # show plot
    plt.show()

# define sigmoid function
# math: refer to https://en.wikipedia.org/wiki/Sigmoid_function or slides
def sigmoid(theta, X):
    #########################################################################
    # Full Mark: 1                                                          #
    # TODO:                                                                 #
    # 1. implement the sigmoid function over input theta and X
    #########################################################################
    y_ = np.dot(X, theta)
    s = 1.0 / (1 + np.exp(-y_))
    #########################################################################
    #                       END OF YOUR CODE                                #
    #########################################################################

    return s

# define cost function with sigmoid function
def cost(theta, X, y):
    #########################################################################
    # Full Mark: 2                                                          #
    # TODO:                                                                 #
    # 1. implement the cross entropy loss function with sigmoid             #
    #########################################################################
    hx = sigmoid(theta, X)
    if np.sum(1 - hx < 1e-10) != 0:
        return np.inf
    co = -np.mean(np.multiply(y, np.log(hx)) + np.multiply(1 - y, np.log(1 - hx)))
    #########################################################################
    #                       END OF YOUR CODE                                #
    #########################################################################
    return co

# the gradient of the cost is a vector of the same length as θ where the jth element (for j = 0, 1, . . . , n)
def gradient(theta, X, y):
    #########################################################################
    # Full Mark: 2                                                          #
    # TODO:                                                                 #
    # 1. calculate the gradients using theta and sigmoid                    #
    # Hint: X may need to be transposed to do matrix operation              #
    #########################################################################
    y_ = sigmoid(theta, X)
    grad = np.dot(X.T,  y_ - y)/len(X)
    #########################################################################
    #                       END OF YOUR CODE                                #
    #########################################################################
    return grad

# draw decision boudary
def draw_decision_boudary(final_theta,x,y):
    #########################################################################
    # Full Mark: 2                                                          #
    # TODO:                                                                 #
    # 1. plot the decision boudary on the raw data                          #
    # 2. set title for the plot                                             #
    # 3. set label for x,y axis                                             #
    # Note, this scatter plot has two different type of points              #
    #########################################################################
    plt.title("Logistic Regression")
    plt.xlabel("x")
    plt.ylabel("y")
    pos = np.where(y == 0)
    neg = np.where(y == 1)
    plt.scatter(x[pos, 1], x[pos, 2], marker='x', color='r', label='class0')
    plt.scatter(x[neg, 1], x[neg, 2], marker='o', color='b', label='class1')

    plot_x = np.array([np.min(x[:, 1]) - 1, np.max(x[:, 1] + 1)])
    plot_y = -1 / final_theta[2] * (final_theta[1] * plot_x + final_theta[0])

    plt.plot(plot_x, plot_y)

    plt.legend()
    #########################################################################
    #                       END OF YOUR CODE                                #
    #########################################################################

    # show plot
    plt.show()

# predict for new X
def predict(theta, X):
    #########################################################################
    # Full Mark: 1                                                          #
    # TODO:                                                                 #
    # 1. predict the value using theta and sigmoid                          #
    # 2. convert the predicted value to 0/1                                 #
    # That's how it is called Logistic regression                           #
    #########################################################################
    m = len(X)
    predict_labels = np.zeros((m,))
    pos = np.where(sigmoid(theta, X) >= 0.5)
    neg = np.where(sigmoid(theta, X) < 0.5)
    predict_labels[pos] = 1
    predict_labels[neg] = 0
    #########################################################################
    #                       END OF YOUR CODE                                #
    #########################################################################

    return predict_labels

# calculate accuracy
def accurate(predictions, y):
    #########################################################################
    # Full Mark: 1                                                          #
    # TODO:                                                                 #
    # 1. calculate the accuracy value                                       #
    # Note that you coud not import extra library                           #
    #########################################################################
    accuracy_score = np.sum(predictions == y) / len(y)
    #########################################################################
    #                       END OF YOUR CODE                                #
    #########################################################################
    return accuracy_score

if __name__ == '__main__':
    draw_data(x, y)

    x = np.concatenate((np.array([np.ones(len(y))]).T, x), axis=1)
    theta = np.zeros(x.shape[1])

    result = opt.fmin_tnc(func=cost, x0=theta, fprime=gradient, args=(x, y))
    final_theta = result[0]
    final_cost = cost(final_theta, x, y)
    predictions = predict(final_theta, x)
    accuracy = accurate(predictions, y)
    print("final cost is " + str(final_cost))
    print("accuracy is " + str(accuracy))

    draw_decision_boudary(final_theta, x, y)


import numpy as np

from Matrices import *

print("Determinant of diagonal matrix:")
print(np.linalg.det(diag_A))
diag_A_rev = np.linalg.inv(diag_A)
print("Condition number of diagonal matrix:")
print(np.linalg.norm(diag_A_rev) * np.linalg.norm(diag_A))

print("Determinant of random matrix:")
print(np.linalg.det(random_A))
random_A_rev = np.linalg.inv(random_A)
print("Condition number of random matrix:")
print(np.linalg.norm(random_A_rev) * np.linalg.norm(random_A))

print("Determinant of Hilbert matrix:")
print(np.linalg.det(hilbert_A))
hilbert_A_rev = np.linalg.inv(hilbert_A)
print("Condition number of Hilbert matrix:")
print(np.linalg.norm(hilbert_A_rev) * np.linalg.norm(hilbert_A))


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

tick = ['AMZN', 'AAPL', 'NFLX', 'XOM', 'T']
price_data = web.get_data_yahoo(tick,
                           start = '2014-01-01',
                           end = '2018-05-31')['Adj Close']

log_ret = np.log(price_data/price_data.shift(1))

cov_mat = log_ret.cov() * 252
print(cov_mat)

# Simulating 5000 portfolios
num_port = 5000
# Creating an empty array to store portfolio weights
all_wts = np.zeros((num_port, len(price_data.columns)))
# Creating an empty array to store portfolio returns
port_returns = np.zeros((num_port))
# Creating an empty array to store portfolio risks
port_risk = np.zeros((num_port))
# Creating an empty array to store portfolio sharpe ratio
sharpe_ratio = np.zeros((num_port))

for i in range(num_port):
    wts = np.random.uniform(size = len(price_data.columns))
    wts = wts/np.sum(wts)

    # saving weights in the array
    all_wts[i,:] = wts

    # Portfolio Returns

    port_ret = np.sum(log_ret.mean() * wts)
    port_ret = (port_ret + 1) ** 252 - 1

    # Saving Portfolio returns

    port_returns[i] = port_ret

    # Portfolio Risk

    port_sd = np.sqrt(np.dot(wts.T, np.dot(cov_mat, wts)))

    port_risk[i] = port_sd

    # Portfolio Sharpe Ratio
    # Assuming 0% Risk Free Rate

    sr = port_ret / port_sd
    sharpe_ratio[i] = sr

names = price_data.columns
min_var = all_wts[port_risk.argmin()]
print(min_var)

max_sr = all_wts[sharpe_ratio.argmax()]
print(max_sr)

print(sharpe_ratio.max())

print(port_risk.min())

min_var = pd.Series(min_var, index=names)
min_var = min_var.sort_values()
fig = plt.figure()
ax1 = fig.add_axes([0.1,0.1,0.8,0.8])
ax1.set_xlabel('Asset')
ax1.set_ylabel("Weights")
ax1.set_title("Minimum Variance Portfolio weights")
min_var.plot(kind = 'bar')
plt.show();

max_sr = pd.Series(max_sr, index=names)
max_sr = max_sr.sort_values()
fig = plt.figure()
ax1 = fig.add_axes([0.1,0.1,0.8,0.8])
ax1.set_xlabel('Asset')
ax1.set_ylabel("Weights")
ax1.set_title("Tangency Portfolio weights")
max_sr.plot(kind = 'bar')
plt.show();

fig = plt.figure()
ax1 = fig.add_axes([0.1,0.1,0.8,0.8])
ax1.set_xlabel('Risk')
ax1.set_ylabel("Returns")
ax1.set_title("Portfolio optimization and Efficient Frontier")
plt.scatter(port_risk, port_returns)
plt.show();


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

def levy(mu, c, x):
    try:
        y = math.sqrt(0.5/(2*math.pi))*(math.e**(-c/(2*(x-mu)))/(x-mu)**(3/2))
    except:
        y = 0
    return y

if __name__ == "__main__" :
    mu = 0

    xList = []
    yList1 = []
    yList2 = []
    yList3 = []
    yList4 = []

    for i in np.arange(0, 2, 0.001) :
        xList.append(i)
        yList1.append(levy(mu, 0.5, i))
        yList2.append(levy(mu, 1, i))
        yList3.append(levy(mu, 2, i))
        yList4.append(levy(mu, 4, i))

    plt.plot(xList, yList1)
    plt.plot(xList, yList2)
    plt.plot(xList, yList3)
    plt.plot(xList, yList4)
    plt.legend(["c=0.5", "c=1", "c=2", "c=4"])
    plt.show()


"""
Problem 10
The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17.

Find the sum of all the primes below two million.
"""
import numpy as np

# below is example with Fermat's small theorem - which works, but is slow...

def fermat_primality(number, runs):
    main = []

    def fermat_test(n):
        x = np.random.randint(2, n - 2)
        t = x ** (n - 1)

        if t % n == 1:
            return True
        else:
            return False

    for i in range(runs):
        if fermat_test(number):
            main.append(True)
        else:
            main.append(False)

    if False in main:
        return False

    return True

def execute_fermat(n):
    fermat_primes = [2, 3]

    for j in range(5, n + 1):
        if fermat_primality(number=j, runs=2):
            fermat_primes.append(j)
            print(j)

# execute_fermat(2000000)

# implementation of Sieve of Eratosthenes - much more efficient

def sieve_of_eratosthenes(n):
    # set can only contain unique values
    non_primes = set()
    primes = set()

    for i in range(2, n + 1):  # run numeral n (n + 1) because 0 count
        # sets are efficient for lookups like below

        if i not in non_primes:

            # do sieve cross-out with distance i and start i^2, end numeral n
            non_primes.update(range(i**2, n + 1, i))

            # add i to primes, because it hasn't been crossed yet, and must be prime
            primes.add(i)

    # return sorted set of primes
    return sorted(primes)

print(sum(sieve_of_eratosthenes(2000000)))

Solutions/Problem 10 - Summation of primes.py


import numpy as np
from scipy.signal import convolve2d

def matlab_style_gauss2D(shape=(11,11),sigma=1.5):
    """
    2D gaussian mask - should give the same result as MATLAB's
    fspecial('gaussian',[shape],[sigma])
    """
    m,n = [(ss-1.)/2. for ss in shape]
    y,x = np.ogrid[-m:m+1,-n:n+1]
    h = np.exp( -(x*x + y*y) / (2.*sigma*sigma) )
    h[ h < np.finfo(h.dtype).eps*h.max() ] = 0
    sumh = h.sum()
    if sumh != 0:
        h /= sumh
    return h

def ssim_index(img1, img2, K=[0.01, 0.03], window=None, L=255):
    """ Calculate the structural similarity between two images

    Args:
        img1 ([type]): [description]
        img2 ([type]): [description]
        K ([type]): [description]
        window ([type]): [description]
        L ([type]): [description]
    """
    if window is not None:
        window=matlab_style_gauss2D()

    if img1.shape != img2.shape:
        print("Error: Images has different shapes")
        return None

    M, N = img1.shape

    if (M < 11 or N < 11):
        print("Error: wrong shape")
        return None

    # Maybe it's necessary to convert rgb to YCbCr

    C1 = (K[0]*L)**2
    C2 = (K[1]*L)**2

    window = window/window.sum()    # Normalize filter

    mu1 = convolve2d(img1, np.rot90(window), mode='valid')
    mu2 = convolve2d(img2, np.rot90(window), mode='valid')

    mu1_sq = mu1*mu1
    mu2_sq = mu2*mu2
    mu1_mu2 = mu1*mu2

    sigma1_sq = convolve2d(img1*img1, np.rot90(window), mode='valid')
    sigma2_sq = convolve2d(img2*img2, np.rot90(window), mode='valid')
    sigma12 = convolve2d(img1*img2, np.rot90(window), mode='valid')

    if(C1>0 and C2>0):
        ssim_map =  ((2*mu1_mu2 + C1)*(2*sigma12 + C2))/((mu1_sq + mu2_sq + C1)*(sigma1_sq + sigma2_sq + C2))
    else:
        numerator1 = 2*mu1_mu2 + C1
        numerator2 = 2*sigma12 + C2
        denominator1 = mu1_sq + mu2_sq + C1
        denominator2 = sigma1_sq + sigma2_sq + C2
        ssim_map = np.ones(mu1.shape)
        index = (denominator1*denominator2 > 0)
        ssim_map[index] = (numerator1[index]*numerator2[index])/(denominator1[index]*denominator2[index])
        index = (denominator1 != 0) & (denominator2 == 0)
        ssim_map[index] = numerator1[index]/denominator1[index]

    mssim = np.mean(ssim_map)

    return mssim


'''
Metrics to measure forecast error
These are measures currently not found in sklearn or statsmodels
'''
import numpy as np

def mean_absolute_percentage_error(y_true, y_pred):
    '''
    MAPE

    Parameters:
    --------
    y_true -- np.array actual observations from time series
    y_pred -- the predictions to evaluate

    Returns:
    -------
    float, scalar value representing the MAPE (0-100)
    '''
    #y_true, y_pred = np.array(y_true), np.array(y_pred)
    return np.mean(np.abs((y_true - y_pred) / y_true)) * 100

def coverage(y_true, pred_intervals):
    '''
    Calculates the proportion of the true
    values are that are covered by the lower
    and upper bounds of the prediction intervals

    Parameters:
    -------
    y_true -- arraylike, actual observations
    pred_intervals -- np.array, matrix (hx2)
    '''
    y_true = np.asarray(y_true)
    lower = np.asarray(pred_intervals.T[0])
    upper = np.asarray(pred_intervals.T[1])

    cover = len(np.where((y_true > lower) & (y_true < upper))[0])
    return cover / len(y_true)


import numpy as np
from scipy.stats import entropy

from osm.data_streams.active_learner.measures.abstract_measure import AbstractMeasure

class Entropy(AbstractMeasure):
    """
    Calculates the entropy
    """
    def calculate(self, proba):
        """
        Calculate the entropy
        :param proba: the probabilities of prediction
        :return: the entropy scores
        """
        return np.apply_along_axis(entropy, 1, proba, base=proba.shape[1])

    def check(self, entropy_x, threshold):
        """
        Checks if the instance x with entropy x can be sampled.
        For entropy higher values mean more uncertain
        :param entropy_x: the entropy of x
        :param threshold: the threshold to compare with
        :return: True if it satisfies the threshold condition
        """
        return self.get_max_value() - entropy_x < threshold

    def get_name(self):
        return "entropy"


"""

Python - Matrix
Matrix is a special case of two dimensional array where each data element is of strictly same size.
So every matrix is also a two dimensional array but not vice versa. Matrices are very important data
structures for many mathematical and scientific calculations. As we have already discussed two dimnsional
array data structure in the previous chapter we will be focusing on data structure operations specific to matrices in this chapter.

We also be using the numpy package for matrix data manipulation.

Matrix Example
Consider the case of recording temprature for 1 week measured in the morning, mid-day,
evening and mid-night. It can be presented as a 7X5 matrix using an array and the reshape method available in numpy.

"""

from numpy import *
a = array([['Mon',18,20,22,17],['Tue',11,18,21,18],
		   ['Wed',15,21,20,19],['Thu',11,20,22,21],
		   ['Fri',18,17,23,22],['Sat',12,22,20,18],
		   ['Sun',13,15,19,16]])

m = reshape(a,(7,5))
print(m)

"""

The above data can be represented as a two dimensional array as below.

[['Mon' '18' '20' '22' '17']
 ['Tue' '11' '18' '21' '18']
 ['Wed' '15' '21' '20' '19']
 ['Thu' '11' '20' '22' '21']
 ['Fri' '18' '17' '23' '22']
 ['Sat' '12' '22' '20' '18']
 ['Sun' '13' '15' '19' '16']]

"""


# Developed by Bayram Barış Sarı
# E-mail = bayrambariss@gmail.com
# Tel = +90 539 593 7501
#
# This is an implementation of Singular
# Value Decomposition.
#
# It finds SVD and plots for 4 different
# ranks: 1,5,20,50.

import numpy as np
import matplotlib.pyplot as plt
import scipy.linalg as la
from PIL import Image
from math import isclose

# I used this function for comparing calculated matrices with builtin SVD's matrices
# def print_to_file(matrix):
#     mat = np.matrix(matrix)
#     with open('outfile.txt', 'wb') as f:
#         for line in mat:
#             np.savetxt(f, line, fmt='%.2f')

def calculate(A):
    m = A.shape[0]
    n = A.shape[1]
    S = np.zeros(n)

    # finding eigenvectors with biggest eigenvalues of A*transpose(A)
    helper = np.matmul(A, np.transpose(A))
    eigenvalues, eigenvectors = la.eigh(helper)
    # descending sort of all the eigenvectors according to their eigenvalues
    index = eigenvalues.argsort()[::-1]
    eigenvalues = eigenvalues[index]
    eigenvectors = eigenvectors[:, index]
    V = eigenvectors

    # S is a diagonal matrix that keeps square root of eigenvalues
    j = 0
    for i in eigenvalues:
        if j == S.size:
            break
        elif i >= 0:
            S[j] = np.sqrt(i)
            j += 1
    # same finding process for transpose(A)*A
    helper = np.matmul(np.transpose(A), A)
    eigenvalues, eigenvectors = la.eigh(helper)
    # descending sort of all the eigenvectors according to their eigenvalues
    index = eigenvalues.argsort()[::-1]
    eigenvalues = eigenvalues[index]
    eigenvectors = eigenvectors[:, index]
    U = np.transpose(eigenvectors)

    # S is a diagonal matrix that keeps square root of eigenvalues
    for i in eigenvalues1:
        if j == S.size:
            break
        elif i >= 0:
            S[j] = np.sqrt(i)
            j += 1

    # sorting S in descending order
    S[::-1].sort()
    # print_to_file(S)

    return U, S, V

def plot(img, Ur, Sr, Vr, Ug, Sg, Vg, Ub, Sb, Vb):
    rank = [1, 5, 20, 50]
    for i in rank:
        # calculating V*S*transpose(U) for each channel
        x = Vr[:, 0:i]
        y = Sr[0:i]
        xy = x.dot(np.diag(y))
        z = Ur[0:i]
        merged = xy.dot(z)
        img[:, :, 0] = merged.T

        x = Vg[:, 0:i]
        y = Sg[0:i]
        xy = x.dot(np.diag(y))
        z = Ug[0:i]
        merged = xy.dot(z)
        img[:, :, 1] = merged.T

        x = Vb[:, 0:i]
        y = Sb[0:i]
        xy = x.dot(np.diag(y))
        z = Ub[0:i]
        merged = xy.dot(z)
        img[:, :, 2] = merged.T

        plt.title("Implemented SVD, Rank: %d" % i)
        plt.imshow(img)
        plt.show()

def check_sign_U(U, builtin):
    for i in range(builtin.shape[0]):
        if not isclose(U[i][0], builtin[0][i]):
            U[i] *= -1

    return U

def check_sign_V(V, builtin):
    for i in range(builtin.shape[0]):
        if not isclose(V[0][i], builtin[i][0]):
            V[:, i] *= -1

    return V

def plot_builtin(Ur, Sr, Vr, Ug, Sg, Vg, Ub, Sb, Vb, img):
    rank = [1, 5, 20, 50]
    for i in rank:
        x = Ur[:, 0:i]
        y = Sr[0:i]
        xy = x.dot(np.diag(y))
        z = Vr[0:i]
        merged = xy.dot(z)
        img[:, :, 0] = merged

        x = Ug[:, 0:i]
        y = Sg[0:i]
        xy = x.dot(np.diag(y))
        z = Vg[0:i]
        merged = xy.dot(z)
        img[:, :, 1] = merged

        x = Ub[:, 0:i]
        y = Sb[0:i]
        xy = x.dot(np.diag(y))
        z = Vb[0:i]
        merged = xy.dot(z)
        img[:, :, 2] = merged

        plt.title("Builtin SVD, Rank: %d" % i)
        plt.imshow(img)
        plt.show()

def main():
    # read the image and normalize it
    image = np.array(Image.open('data.jpg'))
    image = image / 255
    # plt.imshow(image)
    # plt.show()

    # Split the image to three channels, Red, Green and Blue
    R = image[:, :, 0]
    G = image[:, :, 1]
    B = image[:, :, 2]

    # Calculate builtin SVD function, it has been used for checking eigenvectors and eigenvalues
    new_img = np.zeros(image.shape)
    Ur, Sr, Vr = la.svd(R, full_matrices=True)
    Ug, Sg, Vg = la.svd(G, full_matrices=True)
    Ub, Sb, Vb = la.svd(B, full_matrices=True)
    # plot_builtin(Ur, Sr, Vr, Ug, Sg, Vg, Ub, Sb, Vb, new_img)

    # Calculate own SVD and plot it for rank = [1,5,20,50]
    new_img2 = np.zeros(image.shape)

    U_r, S_r, V_r = calculate(R.T)
    U_r = check_sign_U(U_r, Ur)
    V_r = check_sign_V(V_r, Vr)

    U_g, S_g, V_g = calculate(G.T)
    U_g = check_sign_U(U_g, Ug)
    V_g = check_sign_V(V_g, Vg)

    U_b, S_b, V_b = calculate(B.T)
    U_b = check_sign_U(U_b, Ub)
    V_b = check_sign_V(V_b, Vb)

    plot(U_r, S_r, V_r, U_g, S_g, V_g, U_b, S_b, V_b, new_img2)

if __name__ == "__main__":
    main()


import numpy as np

def gaussian(X, mu, cov):
    """
        Returns the pdf of a Gaussian kernel

        :param X: Input data.
        :type X: :obj:`numpy.ndarray`
        :param mu: Mean of the gaussian distribution.
        :type mu: :obj:`numpy.ndarray`
        :param cov: Covariance matrix.
        :type cov: :obj:`numpy.ndarray`

        :formula:

            .. math:: \\dfrac{1}{(2 \\pi)^{\\frac{n}{2}} \\sqrt{\\det{\\sigma}}} e^{-\\dfrac{1}{2} \\dfrac{X'X}{\\sigma^{2}}}

        :references: * Murphy, K. P. (2012). Machine learning: a probabilistic perspective. MIT press.
    """
    X_centered = X - mu
    n = X.shape[1]
    _a = (1 / ((2 * np.pi) ** (n / 2) * np.linalg.det(cov) ** 0.5))
    _b = np.exp(-0.5 * np.dot(np.dot(X_centered, np.linalg.inv(cov)), X_centered.T))

    return np.diagonal(_a * _b).reshape(-1, 1)


import numpy as np
import time
MAX = 100;
def create_tridiag(a, b, c, n):
    A = np.zeros((n, n))
    for i in range(n):
        A[i][i] = b
        if i < n - 1:
            A[i + 1][i] = a
            A[i][i + 1] = c
    return A

def Doolittle(mat, n):
    lower = np.zeros((n,n))
    upper = np.zeros((n,n))

    for i in range(n):

        # Upper Triangular
        for k in range(i, n):

            # Summation of L(i, j) * U(j, k)
            sum = 0;
            for j in range(i):
                sum += (lower[i][j] * upper[j][k]);

            # Evaluating U(i, k)
            upper[i][k] = mat[i][k] - sum;

        # Lower Triangular
        for k in range(i, n):
            if (i == k):
                lower[i][i] = 1;  # Diagonal as 1
            else:

                # Summation of L(k, j) * U(j, i)
                sum = 0;
                for j in range(i):
                    sum += (lower[k][j] * upper[j][i]);

                # Evaluating L(k, i)
                lower[k][i] = int((mat[k][i] - sum) /
                                  upper[i][i]);

            # setw is for displaying nicely
    print("Lower Triangular\t\tUpper Triangular");
    return lower, upper

n = 50
a = create_tridiag(1, 4, -1, n)
b = [1 for i in range(n)]
start = time.time()
L, U = Doolittle(a, n);
end = time.time()

print("L: ")
print(L)
print("U: ")
print(U)
print("Time: ", end - start)


# loss functions

import jax.numpy as np

def mse(y_pred, y_true):
    ''' Description: mean-square-error loss
        Args:
            y_pred : value predicted by method
            y_true : ground truth value
            eps: some scalar
    '''
    return np.sum((y_pred - y_true)**2)

def cross_entropy(y_pred, y_true, eps=1e-9):
    ''' Description: cross entropy loss, y_pred is equivalent to logits and y_true to labels
        Args:
            y_pred : value predicted by method
            y_true : ground truth value
            eps: some scalar
    '''
    return - np.sum(y_true * np.log(y_pred + eps))


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

author = "Oscar Ding"

def rbf_kernel_pca(X, gamma, n_components):
    """
    RBF kernel PCA implementation.

    Parameters
    ------------
    X: {NumPy ndarray}, shape = [n_samples, n_features]

    gamma: float
      Tuning parameter of the RBF kernel

    n_components: int
      Number of principal components to return

    Returns
    ------------
     X_pc: {NumPy ndarray}, shape = [n_samples, k_features]
       Projected dataset
     lambdas: list
       Eigenvalues

    """
    # Calculate pairwise squared Euclidean distances in the MxN dimensional dataset.
    sq_dists = pdist(X, 'sqeuclidean')

    # Convert pairwise distances into a square matrix.
    mat_sq_dists = squareform(sq_dists)

    # Compute the symmetric kernel matrix.
    K = exp(-gamma * mat_sq_dists)

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

    # Obtaining eigenpairs from the centered kernel matrix
    # scipy.linalg.eigh returns them in ascending order
    eigvals, eigvecs = eigh(K)
    eigvals, eigvecs = eigvals[::-1], eigvecs[:, ::-1]

    # Collect the top k eigenvectors (projected samples)
    alphas = np.column_stack((eigvecs[:, i] for i in range(n_components)))

    # Collect the corresponding eigenvalues
    lambdas = [eigvals[i] for i in range(n_components)]

    return alphas, lambdas


"""
demo_nonlinear_programming_equality_constraints.py

(Non)linear objective function and (non)linear equality constraints

m = number of equality constraints;
n = number of parameters;

Objective function:
    Minimize f(X), where
    X = [x1, ..., xn].T is vector of variables;
    X* is extreme point (MIN or MAX);

Equality constrains:
    Subject to equality constraints: h(X);
    h(X) = [h1(X), ..., hn(X)].T is vector of constraints;
    m < n;

Lagrange algorithm

Lagrangian function:
    l(X, Lambda) = f(X) + lambda.T @ h(X);
    Lambda = [lambda1, ..., lambdan].T is vector of langrange multipliers;
    Lambda* is extreme point;

1st Condition:
    Gradient of lagrangian function:
        Dl(X*, Lambda*) = Df(X*) + Dh(X*).T @ Lambda = 0.T;

2nd Condition:
    Normal space formed by all normal vectors of f(X) and h(X), i.e. Df(X) and Dh(X), at X*:
        N(Dh(X*).T) is null space of Dh(X*).T;
    Tangent space formed by all tangent (and shared!) vectors of f(X() and h(X) at X*:
        T(X*) is tangent space;
    Hessian of l(X, lambda):
        Hl(X, lambda) = Hf(X) + lambda1 * Hh1(X) + ... + lambdan * Hhn(X);

    Tangent and Normal spaces are orthogonal:
        T(X*) = N(Dh(X*).T);

    Solution lies in the tangent space:
        T(X*).T @ Hl(X*, lambda*) @ T(X*) > 0, X* is MIN;
"""

import numpy as np

"""
Problem # 1
Minimize f(X) = x1^2 + 2x1x2 + 3x2^2 + 4x1 + 5x2 + 6x3;
Constraints:
        h1(X) = x1 + 2x2 - 3 = 0;
        h2(X) = 4x1 + 5x3 - 6 = 0;

X = [x1, x2, x3].T;
Lambda = [lambda1, lambda2].T;

Df(X) = [2x1 + 2x2 + 4
         2x1 + 6x2 + 5
         6];

Dh(X) = [1, 2, 0
         4, 0, 5];

Solve system of eqs.:
1. Dl(X, Lambda) = [2x1 + 2x2 + 4 + lambda1 * [1, 2, 0].T + lambda2 * [4, 0, 5].T = 0.T;
                 2x1 + 6x2 + 5
                 6];
2. x1 + 2x2 - 3 = 0;
3. 4x1 + 5x3 - 6 = 0;

Hl(X*, Lambda*) = [2, 2, 6
                   2, 6, 0
                   0, 0, 0];

T(X*) = [-5/4, 5/8, 1].T;
"""

A = np.array([[2, 2, 0, 1, 4], [2, 6, 0, 2, 0], [0, 0, 0, 0, 5],
              [1, 2, 0, 0, 0], [4, 0, 5, 0, 0]]);
B = np.array([[-4], [-5], [-6], [3], [6]]);

solution = np.linalg.solve(A, B);
X_opt = solution[0:3]; # X*
lambda_opt = solution[3:-1]; # lambda*
print('X:');
print(X_opt);

"""
Problem # 2
X = [x1, x2].T;
Q = np.array([[8, 2 * np.sqrt(2)], [2 * np.sqrt(2), 10], [5 * np.sqrt(2), 1]]);
C = np.array([[3], [6], [8]]);
D = 24;
A = np.random.rand(2, 3);
B = np.random.rand(2, 1);
Minimize f(X) = 1 / 2 * X.T @ Q @ X - C.T @ X + D;
Constraints:
        h(X) = A @ X - B = 0;

Df(X) = X.T @ Q - C;
Dh(X) = A;

Solve system of eqs.:
1. Dl(X, Lambda) = X.T @ Q - C.T + lambda.T @ A = 0.T;
2. A @ X - B = 0;

Hl(X*, lambda*) = Q;
"""

Q = np.array([[8, 2 * np.sqrt(2), 11], [2 * np.sqrt(2), 10, 1], [0.5 * np.sqrt(2), 5, 2]]);
C = np.array([[3], [6], [8]]);
D = 24;
A = np.random.rand(2, 3);
B = np.random.rand(2, 1);

Qinv = np.linalg.inv(Q);
Qinv_times_At = Qinv @ A.T;

lambda_opt = np.linalg.inv(Qinv_times_At.T @ A.T) @ (B - Qinv_times_At.T @ C);
X_opt = Qinv @ C + Qinv_times_At @ lambda_opt;
print('X:');
print(X_opt);


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

DELTA = 0.01

m2 = 1 / 82

f = lambda x: x - (1 - m2) * (x + m2) / (abs(x + m2) ** 3) - m2 * (x - 1 + m2) / (abs(x - 1 + m2) ** 3)

segments = [[-2, -m2 - DELTA],
            [-m2 + DELTA, 1 - m2 - DELTA],
            [1 - m2 + DELTA, 2]]

roots = [brentq(f, segments[i][0], segments[i][1]) for i in range(len(segments))]

x = [np.linspace(segments[i][0], segments[i][1], round(1 / DELTA)) for i in range(len(segments))]
y = [f(x[i]) for i in range(len(segments))]

plt.plot(roots, [0, 0, 0], marker="o", linestyle='')
for i in range(len(segments)):
    plt.plot(x[i], y[i])

plt.axhline(color="grey", ls="--", zorder=-1)
plt.axvline(color="grey", ls="--", zorder=-1)

plt.axvline(color="red", ls=":", zorder=-1, x=-m2)
plt.axvline(color="red", ls=":", zorder=-1, x=1 - m2)

plt.axis([-2, 2, -10, 10])
plt.show()

print(roots)


# kurva bezier  adalah kurva parametrik yang sering
# digunkan dalam pemodelan permukaan halus dalam
# grafik komputer dan banuak bidang terkait lainnya.
# kurva ini dapat diskalakan tanpa batas.
# digunakan juga dalam mengendalikan animasi.

from __future__ import annotations

from scipy.special import comb  # type: ignore

class BezierCurve:
    def __init__(self, list_of_points: list[tuple[float, float]]):
        """
        list_of_points: titik kontrol pada bidang xy yang akan
        di interpolasi. ini poin mengontrol dari kurva bezier.
        """
        self.list_of_points = list_of_points

        # mementukan fleksibilitas kurva
        # derajat = 1 akan menghasilkan garis lurus
        self.degree = len(list_of_points) - 1

    def basis_function(self, t: float) -> list[float]:
        """
        fungsi basis menentukan bobot setiap titik kendali
        pada waktu t.
        t: nilai waktu antar 0 dan 1 inklusif untuk evaluasi
        basis kurva.
        return: mengembalikan nilai x, y dari fungsi dasar
        pada waktu t.

        >>> curve = BezierCurve([(1, 1), (1, 2)])
        >>> curve.basis_function(0)
        [1.0, 0.0]
        >>> curve.basis_function(1)
        [0.0, 1.0]
        """
        assert 0 <= t <= 1, "waktu t harus antara 0 dan 1."
        output_values: list[float] = []
        for i in range(len(self.list_of_points)):
            # basis fungsi dari setiap 1
            output_values.append(
                comb(self.degree, i) * (1 - t) ** (self.degree - i) * (t**i)
            )

        assert round(sum(output_values), 5) == 1

        return output_values

    def bezier_curve_function(self, t: float) -> tuple[float, float]:
        """
        fungsi untuk menghasilkan nilai kurva bezier pada waktu t.
        t: nilai waktu untuk evaluasi fungsi bezier
        return: mengembalikan kordinaat x, y dari kurva bezier
        pada waktu t.

        titik pertama kurva adalah ketika t = 0
        titik terakhir dalam kurva adalah ketika t = 1

        >>> curve = BezierCurve([(1, 1), (1, 2)])
        >>> curve.bezier_curve_function(0)
        (1.0, 1.0)
        >>> curve.bezier_curve_function(1)
        (1.0, 2.0)
        """

        assert 0 <= t <= 1, "waktu t harus antara 0 dan 1."

        basis_function = self.basis_function(t)
        x = 0.0
        y = 0.0

        for i in range(len(self.list_of_points)):
            x += basis_function[i] * self.list_of_points[i][0]
            y += basis_function[i] * self.list_of_points[i][1]

        return (x, y)

    def plot_curve(self, step_size: float = 0.01):
        """
        plit kurva bezier menggunakan matplotlib
        step_size: mendefinisikan langkah untuk
        mengevaluassi kurva bezier.

        semakin kecil ukurang langkah, semakin halus
        kurva yang dihasilkan.
        """
        from matpltlib import pyplot as plt  # type: ignore

        to_plot_x: list[float] = []
        to_plot_y: list[float] = []

        t = 0.0
        while t <= 1:
            value = self.bezier_curve_function(t)
            to_plot_x.append(value[0])
            to_plot_y.append(value[1])
            t += step_size

        x = [i[0] for i in self.list_of_points]
        y = [i[1] for i in self.list_of_points]

        plt.plot(
            to_plot_x,
            to_plot_y,
            color="blue",
            label="derajat kurva "
            + str(
                self.degree,
            ),
        )
        plt.scatter(x, y, color="red", label="Control Point")
        plt.legend()
        plt.show()

if __name__ == "__main__":
    import doctest

    doctest.testmod()

    BezierCurve([(1, 2), (3, 5)]).plot_curve()
    BezierCurve([(0, 0), (5, 5), (5, 0)]).plot_curve()
    BezierCurve([(0, 0), (5, 5), (5, 0), (2.5, -2.5)]).plot_curve()


import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d

X = np.linspace(-2, 2)
Y = np.linspace(-2, 2)
x, y = np.meshgrid(X, Y)
t = x**2 + y**2  # small efficiency
z = np.cos(2*np.pi*t)*np.exp(-t)

fig = plt.figure()
ax = fig.add_subplot(projection="3d")
ax.plot_surface(x, y, z, cmap="binary_r")
ax.set_title("Surface with colormap")
ax.set_xlabel("$x$")
ax.set_ylabel("$y$")
ax.set_zlabel("$z$")

plt.show()

fig, ax = plt.subplots()
ax.contour(x, y, z, cmap="binary_r")

ax.set_xlabel("$x$")
ax.set_ylabel("$y$")
ax.set_title("Contour plot with colormap set")

plt.show()


import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.neural_network import MLPRegressor
from sklearn.metrics import mean_squared_error, mean_absolute_error

def regevaluate(t, predict, criterion):
    if criterion == 'mse':
        return mean_squared_error(t, predict)
    else:
        return mean_absolute_error(t, predict)

data = pd.read_csv('housing.data', header=None, sep="\s+").values

number_of_patterns, number_of_attributes = data.shape

x = data[:, 0:number_of_attributes - 1]
t = data[:, number_of_attributes - 1]

lowest_mean_mae = 1000.0
lowest_mean_mse = 1000.0

lowest_n_mae = 0.0
lowest_n_mse = 0.0

max_epoch = 50000

for n in [5, 10, 20, 30, 40, 50]:
    mean_mae = 0.0
    mean_mse = 0.0

    for i in range(9):
        xtrain, xtest, ttrain, ttest = train_test_split(x, t, test_size=0.1)

        model = MLPRegressor(hidden_layer_sizes=n, activation='relu', solver='adam', learning_rate='constant', max_iter=max_epoch, learning_rate_init=0.01)
        model.fit(xtrain, ttrain)

        y = model.predict(xtest)

        mean_mae += regevaluate(ttest, y, 'mae')
        mean_mse += regevaluate(ttest, y, 'mse')

    mean_mae /= 9
    mean_mse /= 9

    if lowest_mean_mae > mean_mae:
        lowest_mean_mae = mean_mae
        lowest_n_mae = n

    if lowest_mean_mse > mean_mse:
        lowest_mean_mse = mean_mse
        lowest_n_mse = n

    print("Mean MAE: {}, N: {}".format(lowest_mean_mae, lowest_n_mae))
    print("Mean MSE: {}, N: {}".format(lowest_mean_mse, lowest_n_mse))

xtrain, xtest, ttrain, ttest = train_test_split(x, t, test_size=0.1)
model = MLPRegressor(hidden_layer_sizes=lowest_mean_mse, activation='relu', solver='adam', learning_rate='constant', max_iter=max_epoch, learning_rate_init=0.01)
model.fit(xtrain, ttrain)
y = model.predict(xtest)

plt.subplot(1, 1, 1)
plt.plot(y, 'r.', markersize=6)
plt.plot(ttest, 'b-', markersize=6)
plt.show()


import numpy as np
import einops

def derive_rotation_matrices(order: int) -> np.ndarray:
    """Calculate a set of rotation matrices for a cyclic symmetry.

    Axis of rotation is the Z axis.
    Matrices are defined
    Rz = [[cos(t), -sin(t),    0],
          [sin(t),  cos(t),    0],
          [     0,       0,    1]]

    Parameters
    ----------
    order : int
        symmetry order

    Returns
    -------
    rotation_matrices: (order, 3, 3) np.ndarray
        matrices defining rotations around the Z axis
    """
    theta = np.linspace(0, 2*np.pi, num=order, endpoint=False)
    cos_theta = np.cos(theta)
    sin_theta = np.sin(theta)

    rotation_matrices = einops.repeat(
        np.eye(3),
        'i j -> new_axis i j',
        new_axis=order
    )
    rotation_matrices[:, 0, 0] = cos_theta
    rotation_matrices[:, 0, 1] = -sin_theta
    rotation_matrices[:, 1, 0] = sin_theta
    rotation_matrices[:, 1, 1] = cos_theta
    return rotation_matrices


import numpy as np

def rmse(predictions, targets):
    """ RMSE function
       Args:
           predictions (1-d array of float): Predicted values.
           targets (1-d array of float): Observed values.
    """
    return np.sqrt(((predictions - targets) ** 2).mean())


import numpy as np
import math

def polar(pt, ang, dist):
    return (pt[0] + dist*np.cos(ang),
            pt[1] + dist*np.sin(ang))

# 2pi is 360 degrees
# pi is 180
# pi/2 is 90
# pi/4 is 45
#print(polar((10,10), np.pi/2, 20))

def angle(pt1, pt2):
    return math.atan2(pt2[1]-pt1[1], pt2[0]-pt1[0])

#print(angle((10,10), (10,20))/np.pi)

# bulge is described here :
# http://www.lee-mac.com/bulgeconversion.html
# which used the function: polar described here:
# http://www.afralisp.net/autolisp/tutorials/calculating-polar-points.php
# 2*pi is 360 degrees

# the function and text below is a translation of this:
# http://www.lee-mac.com/bulgeconversion.html
# ;; Bulge to Arc  -  Lee Mac
# ;; p1 - start vertex
# ;; p2 - end vertex
# ;; b  - bulge
# ;; Returns: (<center> <start angle> <end angle> <radius>)

# (defun LM:Bulge->Arc ( p1 p2 b / a c r )
#     (setq a (* 2 (atan b))
#           r (/ (distance p1 p2) 2 (sin a))
#           c (polar p1 (+ (- (/ pi 2) a) (angle p1 p2)) r)
#     )
#     (if (minusp b)
#         (list c (angle c p2) (angle c p1) (abs r))
#         (list c (angle c p1) (angle c p2) (abs r))
#     )
# )
def bulge2arc(p1, p2, bulge):
    a = 2*np.arctan(bulge)
    r = math.hypot(p2[0]-p1[0], p2[1]-p1[1]) / 2.0 / np.sin(a)
    c = polar(p1, np.pi/2.0-a + angle(p1, p2), r)

    # in the code I stole above, the start and end angles are reversed
    # if bulge is negative. Even from reading the comments on that page,
    # I don't see why that is done.
    # later edit. The page also has this line:
    # "The returned bulge value may be positive or negative, depending
    # upon whether the arc passing through the three points traces a clockwise
    # or counter-clockwise path."
    # negative indicates clockwise.
    # so if going from point A->B at 90 degrees to -90 degress with bulge -1, we pass through 0
    # if going from -90 to 90 also with bulge -1, we don't pass through 0.
    #if (bulge<0):
    #    return (c, np.rad2deg(angle(c, p2)), np.rad2deg(angle(c, p1)), np.absolute(r))
    #else:
    a1 = np.rad2deg(angle(c, p1))
    a2 = np.rad2deg(angle(c, p2))
    # if clockwise (bulge<0) and the angles go from negative to positive, we
    # don't cross 0 degress.
    if (a1<0) and (a2>0) and (bulge<0):
        a1 = a1+360.0
    # if counterclockwise (bulge>0) and the angles go from positive to negative
    # we also don't cross 0 degrees
    if (a1>0) and (a2<0) and (bulge>0):
        a2 = a2+360.0
    return (c, a1, a2, np.absolute(r))

#print(bulge2arc((0,10), (10,0), .5))


'''
奇异值分解
Singular Value Decomposition
author:pgcai
20211201

输入：样本数据
输出：左奇异矩阵，奇异值矩阵，右奇异矩阵
计算特征值： 特征值分解AAT，其中A∈Rm×n为原始样本数据

AAT=UΣΣTUT
得到左奇异矩阵U∈Rm×m和奇异值矩阵Σ′∈Rm×m

间接求部分右奇异矩阵： 求V′∈Rm×n

利用A=UΣ′V′可得

V′=(UΣ′)−1A=(Σ′)−1UTA(1-4)
返回U, Σ′, V′，分别为左奇异矩阵，奇异值矩阵，右奇异矩阵。
'''
import numpy as np

def svd(data):
    '''
    Singular Value Decomposition
    '''
    # 数据必需先转为浮点型，否则在计算的过程中会溢出，导致结果不准确
    data2Float = np.array(data, dtype=float)
    # 计算特征值和特征向量
    eval_sigma1, evec_u = np.linalg.eigh(data2Float.dot(data2Float.T))

    # 降序排列后，逆序输出
    eval1_sort_idx = np.argsort(eval_sigma1)[::-1]
    # 将特征值对应的特征向量也对应排好序
    eval_sigma1 = np.sort(eval_sigma1)[::-1]
    evec_u = evec_u[:,eval1_sort_idx]
    # 计算奇异值矩阵的逆
    eval_sigma1 = np.sqrt(eval_sigma1)
    eval_sigma1_inv = np.linalg.inv(np.diag(eval_sigma1))
    # 计算右奇异矩阵
    evec_part_v = eval_sigma1_inv.dot((evec_u.T).dot(data2Float))

    return evec_u, eval_sigma1, evec_part_v

if __name__=='__main__':
    print("svd")
    import matplotlib.pyplot as plt
    import matplotlib.image as mpimg
    img_eg = mpimg.imread("./data/test2.jpg")
    print(img_eg.shape)
    img_temp = img_eg.reshape(img_eg.shape[0], img_eg.shape[1] * img_eg.shape[2])
    # U,Sigma,VT = np.linalg.svd(img_temp)
    U, Sigma, VT = svd(img_temp)

    # 取前60个奇异值
    sval_nums = 60
    img_restruct1 = (U[:,0:sval_nums]).dot(np.diag(Sigma[0:sval_nums])).dot(VT[0:sval_nums,:])
    img_restruct1 = img_restruct1.reshape(img_eg.shape[0], img_eg.shape[1], img_eg.shape[2])

    print(Sigma.shape)
    print('压缩前数据量 = ', img_eg.shape[0] * img_eg.shape[1] * img_eg.shape[2])
    print('压缩后数据量 = ', img_eg.shape[0]*sval_nums + sval_nums + sval_nums*img_eg.shape[1] * img_eg.shape[2])

    # 取前120个奇异值
    sval_nums = 120
    img_restruct2 = (U[:,0:sval_nums]).dot(np.diag(Sigma[0:sval_nums])).dot(VT[0:sval_nums,:])
    img_restruct2 = img_restruct2.reshape(img_eg.shape[0], img_eg.shape[1], img_eg.shape[2])

    print(Sigma.shape)
    print('压缩前数据量 = ', img_eg.shape[0] * img_eg.shape[1] * img_eg.shape[2])
    print('压缩后数据量 = ', img_eg.shape[0]*sval_nums + sval_nums + sval_nums*img_eg.shape[1] * img_eg.shape[2])

    fig, ax = plt.subplots(1, 3, figsize = (24,32))

    ax[0].imshow(img_eg)
    ax[0].set(title = "src")
    ax[1].imshow(img_restruct1.astype(np.uint8))
    ax[1].set(title = "nums of sigma = 60")
    ax[2].imshow(img_restruct2.astype(np.uint8))
    ax[2].set(title = "nums of sigma = 120")

    plt.show()


import os
import numpy as np
import pandas as pd
import statsmodels.api as sm

from datetime import datetime
from numpy.linalg import inv
from scipy.stats import t

def calc_residuals(df):
    x = df.iloc[:, 0]  # e.g. BTC/USD
    y = df.iloc[:, 1]  # e.g. ETH/USD
    X1 = sm.add_constant(x)
    # Y1 = sm.add_constant(y)

    ols1 = sm.OLS(y, X1).fit()
    # ols2 = sm.OLS(x, Y1).fit()
    # calculate residuals here
    residuals = ols1.resid
    # residuals2 = ols2.resid
    return residuals

def test_stationarity(residuals):
    adf_data = pd.DataFrame(residuals)
    adf_data.columns = ["y"]
    adf_data["drift_constant"] = 1
    # Lag residual
    adf_data["y-1"] = adf_data["y"].shift(1)
    adf_data.dropna(inplace=True)
    # Diff between residual and lag residual
    adf_data["deltay1"] = adf_data["y"] - adf_data["y-1"]
    # Lag difference
    adf_data["deltay-1"] = adf_data["deltay1"].shift(1)
    adf_data.dropna(inplace=True)
    target_y = pd.DataFrame(adf_data["deltay1"], columns=["deltay1"])
    adf_data.drop(["y", "deltay1"], axis=1, inplace=True)

    # Auto regressing the residuals with lag1, drift constant and lagged 1 delta (delta_et-1)
    adf_regressor_model = sm.OLS(target_y, adf_data)
    adf_regressor = adf_regressor_model.fit()

    # Returning the results
    print(adf_data)
    print(adf_regressor.summary())
    return adf_regressor

import numpy,from numpy,from scipy,import statsmodels


from ..weighted import weighted_average
import pandas as pd
import numpy as np
import pytest
from ..errors import NotEnoughOffersOrderbookException

def test1():
    """Simple weighted average"""
    orderbook = [[300, 20], [200, 100], [150, 225]]
    df = pd.DataFrame(orderbook)
    weighted = np.average(df[0], weights=df[1])
    assert round(weighted, 2) == 173.19

def test2():
    """Weighted average of purchased options according to given funds"""
    orderbook = [[300, 20], [200, 100], [150, 225]]
    avg = weighted_average(funds=300 * 20 + 200 * 100 + 150 * 225, offers=orderbook)

    df = pd.DataFrame(orderbook)
    weighted = np.average(df[0], weights=df[1])

    assert avg == weighted

    ###
    avg2 = weighted_average(6000, orderbook)
    assert avg2 == 300

    with pytest.raises(NotEnoughOffersOrderbookException):
        avg3 = weighted_average(6000000, orderbook)


from scipy import stats
import numpy as np

# This method computes entropy for information gain
def entropy(class_y):
    # Input:
    #   class_y         : list of class labels (0's and 1's)

    # Example:
    #    entropy([0,0,0,1,1,1,1,1,1]) = 0.92

    entropy = 0

    if len(class_y) == 0:
        return 0

    class_y = list(class_y)

    # count zeroes and ones
    zeroes = class_y.count(0)
    ones = class_y.count(1)

    if zeroes == 0 or ones == 0:
        return 0

    # implement entropy formula
    total = len(class_y)
    p0 = float(zeroes) / total
    p1 = float(ones) / total
    entropy = -(p0 * np.log2(p0) + p1 * np.log2(p1))

    return entropy

def partition_classes(X, y, split_attribute, split_val):
    # Inputs:
    #   X               : data containing all attributes
    #   y               : labels
    #   split_attribute : column index of the attribute to split on
    #   split_val       : either a numerical or categorical value to divide the split_attribute
    X_left = []
    X_right = []

    y_left = []
    y_right = []

    # Check if numerical or categorical
    is_categorical = isinstance(split_val, str)

    if is_categorical:
        for index, row in enumerate(X):
            if row[split_attribute] == split_val:
                X_left.append(X[index])
                y_left.append(y[index])
            else:
                X_right.append(X[index])
                y_right.append(y[index])
    else:
        for index, row in enumerate(X):
            if row[split_attribute] <= split_val:
                X_left.append(X[index])
                y_left.append(y[index])
            else:
                X_right.append(X[index])
                y_right.append(y[index])

    return X_left, X_right, y_left, y_right

def information_gain(previous_y, current_y):
    # Inputs:
    #   previous_y: the distribution of original labels (0's and 1's)
    #   current_y:  the distribution of labels after splitting based on a particular
    #               split attribute and split value
    """
    Example:

    previous_y = [0,0,0,1,1,1]
    current_y = [[0,0], [1,1,1,0]]

    info_gain = 0.45915
    """
    num_labels = len(previous_y)

    prev_entropy = entropy(previous_y)
    average_entropy = 0

    for row in current_y:
        cond_entropy = entropy(row)
        prob = len(row) / num_labels
        average_entropy += cond_entropy * prob

    info_gain = prev_entropy - average_entropy

    return info_gain

if __name__=="__main__":

    print(entropy([0, 0, 0, 1, 1, 1, 1, 1, 1]))

    X = [[3, 'aa', 10],
         [2, 'cc', 28],
         [1, 'bb', 22],
         [5, 'bb', 32],
         [4, 'cc', 32]]

    y = [1, 1, 0, 0, 1]
    X_left, X_right, y_left, y_right = partition_classes(X, y, 0, 3)
    print(X_left, X_right)
    print(y_left, y_right)

    previous_y = [0,0,0,1,1,1]
    current_y = [[0,0], [1,1,1,0]]
    print(information_gain(previous_y, current_y))


import numpy as np
from scipy import stats
import scipy
import math

# if data is not a frequency distribution
x = np.array([1,2,3,4,5])
mean = np.mean(x)
n = x.size
x_minus_mean= x-mean
x_minus_mean_square = np.square(x_minus_mean)
x_minus_mean_square_sum = np.sum(x_minus_mean_square)

standard_deviation = math.sqrt(x_minus_mean_square_sum/n)
print("standard_deviation 1 : ",standard_deviation)

# if dataset is frequency distribution
x_square = np.square(x)
f = np.array([6,16,24,25,19])
cum_freq = np.array([6,22,46,71,90])
f_x_square = f*x_square

sum_f_x_square = np.sum(f_x_square)
sum_f = np.sum(f)
mean_square = math.pow(mean,2)
standard_deviation = math.sqrt((sum_f_x_square/sum_f) - mean_square)

print("standard_deviation 2 : ",standard_deviation)