#%%
from sklearn import datasets
from sklearn.model_selection import train_test_split
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error
from sklearn.svm import SVR
from sklearn.tree import DecisionTreeRegressor

X, y = datasets.load_boston(return_X_y=True)

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3) # test_size is a proportion of the data you are going to split

X_test, X_validation, y_test, y_validation = train_test_split(X_test, y_test, test_size=0.3) # test_size is a proportion of the data you are going to split

print(f"no samples y: {len(y)}")
print(f"no samples y_train: {len(y_train)}")
print(f"no samples y_test: {len(y_test)}")
print(f"no samples y_validation: {len(y_validation)}")

print(f"no samples x_train: {len(X_train)}")

# %%
np.random.seed(2)

models = [
        DecisionTreeRegressor(splitter="random"),
        SVR(),
        LinearRegression()
        ]

from sklearn import metrics

for model in models:
    model.fit(X_train, y_train)

    y_train_pred = model.predict(X_train)
    y_validation_pred = model.predict(X_validation)
    y_test_pred = model.predict(X_test)

    train_loss = metrics.mean_squared_error(y_train, y_train_pred)
    validation_loss = metrics.mean_squared_error(y_validation, y_validation_pred)
    test_loss = metrics.mean_squared_error(y_test, y_test_pred)

    print(
        f"{model.__class__.__name__}: "
        f"Train loss: {train_loss}"
        f"Validation loss: {validation_loss}"
        f"Test loss: {test_loss}"
        )

# %%
# data leakage example

def calculate_validation_loss(X_train, y_train, X_validation, y_validation):
    model = LinearRegression()

    # Without data leakage, train on train, validate on validation
    model.fit(X_train, y_train)
    y_validation_pred = model.predict(X_validation)
    validation_loss = mean_squared_error(y_validation, y_validation_pred)

    print(f"Validation loss: {validation_loss}")

# Without data leakage, train on train, validate on validation
calculate_validation_loss(X_train, y_train, X_validation, y_validation)

# With data leakage, 50 samples from validation added
fail_X_train = np.concatenate((X_train, X_validation[:50]))
fail_y_train = np.concatenate((y_train, y_validation[:50]))

calculate_validation_loss(fail_X_train, fail_y_train, X_validation, y_validation)

# SUMMARY

# Validation set is used to find info about best algorithms, best set of arguments to algoirthms etc.
# Test set is used to check how our algorithm performs on unseen data
# As we tune algorithms according to validation dataset we cannot use it to check performance
# seed is used to ensure reproducibility. Also multiple runs for experiments are good if our code depends on random initialization heavily (we can take mean results of experiments)
# Data leakage is information from validation (or test) leaking into training
# Data leakage leads to falsely good results and should be avoided
# Rule of thumb: imagine you only have training dataset when doing preprocessing. Anything you calculate from it cannot be used in validation or test


'''
Created on 2013/12/29
@author: Duong Nguyen
@note: Nonnegative Matrix Factorization (NMF) with multiplicative update rules.
@version: Frobenius

V = W*H, where V, W, H >= 0. Here, ">=" means element-wise relation
V: n x m matrix
W: n x b matrix
H: b x m matrix
Minimize_over_W,H || V - W*H || ^ 2 (Frobenius norm)

See also, http://hebb.mit.edu/people/seung/papers/nmfconverge.pdf for more details.
'''

import numpy as np
import matplotlib.pyplot as plt

def fro_distance(A, B):
    """ Compute the Frobenius distance between two matrices A, B.
        d(A, B) = ||A-B||_2 = sqrt{\sum_{i,j} (A_ij-B_ij)^2}
    """
    return np.sqrt(np.sum((A-B)**2))

def factorize(V, b, init="uniform", max_iter=100, tol=1e-8, verbose=False):
    """ Factorization with multiplicative update rules.
        @param init: specify how to initialize W, H. Default: uniformly random in [0,1)
        @param max_iter: Maximum number of iterations of updating
        @param tol: Tolerance value to check if converge
    """

    assert init in ("uniform", "normal"), "Unsupported initialization!"
    n, m = V.shape

    if init == "uniform":
        W, H = np.random.random((n,b)), np.random.random((b,m))
    else:
        W, H = np.random.randn(n,b), np.random.randn(b,m)

    dists = []
    for i in xrange(max_iter):
        WH = W.dot(H)

        cur_dist = fro_distance(V, WH)
        dists.append(cur_dist)

        if verbose and i % 10 == 0:
            print "%d iteration: %f" %(i, cur_dist)

        if cur_dist <= tol:
            break

        # Update H
        nu = (W.T).dot(V)
        de = (W.T).dot(WH)
        H = H*nu/de # element-wise update

        # Update W
        nu = V.dot(H.T)
        de = W.dot(H).dot(H.T)
        W = W*nu/de # element-wise update

    return W, H, dists

def test(plot=False):
    """ Test Frobenius norm-based NMF."""

    V = np.random.random((10, 9))
    W, H, dists = factorize(V, 3, init="uniform", max_iter=200, tol=1e-8, verbose=True)

    if plot:
        plt.figure()
        plt.clf()
        plt.plot(dists, "b-", lw=2)
        plt.xlabel("Iteration")
        plt.ylabel("Frobenius distance as cost function")
        plt.title("Frobenius NMF Demo")
        plt.show()
        plt.savefig("fro_nmf_demo.png") # save figure at current working directory

    print "V =", V
    print "W * H =", W.dot(H)
    print "Frobenius distance d =", dists[-1]

if __name__ == "__main__":
    test(plot=True)


import matplotlib.pyplot as plt
import numpy as np
from matplotlib.colors import LogNorm
from mpl_toolkits.mplot3d import axes3d, Axes3D
from computeCost import *
from gradientDescent import *
from plotData import *

# ===================== Part 1: Plotting =====================
print('Plotting Data...')
data = np.loadtxt('ex1data1.txt', delimiter=',', usecols=(0, 1))
X = data[:, 0]
y = data[:, 1]
m = y.size

plt.ion()
plt.figure(0)
plot_data(X, y)

input('Program paused. Press ENTER to continue')

# ===================== Part 2: Gradient descent =====================
print('Running Gradient Descent...')

X = np.c_[np.ones(m), X]  # Add a column of ones to X

theta = np.zeros(2)  # initialize fitting parameters

# Some gradient descent settings
iterations = 1500
alpha = 0.01

# Compute and display initial cost
print('Initial cost : ' + str(compute_cost(X, y, theta)) + ' (This value should be about 32.07)')

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

print('Theta found by gradient descent: ' + str(theta.reshape(2)))

# Plot the linear fit
plt.figure(0)
line1, = plt.plot(X[:, 1], np.dot(X, theta), label='Linear Regression')
plt.legend(handles=[line1])
plt.pause(0.5)

input('Program paused. Press ENTER to continue')

# Predict values for population sizes of 35,000 and 70,000
predict1 = np.dot(np.array([1, 3.5]), theta)
print('For population = 35,000, we predict a profit of {:0.3f} (This value should be about 4519.77)'.format(predict1*10000))
predict2 = np.dot(np.array([1, 7]), theta)
print('For population = 70,000, we predict a profit of {:0.3f} (This value should be about 45342.45)'.format(predict2*10000))

input('Program paused. Press ENTER to continue')

# ===================== Part 3: Visualizing J(theta0, theta1) =====================
print('Visualizing J(theta0, theta1) ...')

theta0_vals = np.linspace(-10, 10, 100)
theta1_vals = np.linspace(-1, 4, 100)

xs, ys = np.meshgrid(theta0_vals, theta1_vals)
J_vals = np.zeros(xs.shape)

# Fill out J_vals
for i in range(0, theta0_vals.size):
    for j in range(0, theta1_vals.size):
        t = np.array([theta0_vals[i], theta1_vals[j]])
        J_vals[i][j] = compute_cost(X, y, t)

J_vals = np.transpose(J_vals)

fig1 = plt.figure(1)
ax = fig1.gca(projection='3d')
ax.plot_surface(xs, ys, J_vals)
plt.xlabel(r'$\theta_0$')
plt.ylabel(r'$\theta_1$')

plt.figure(2)
lvls = np.logspace(-2, 3, 20)
plt.contour(xs, ys, J_vals, levels=lvls, norm=LogNorm())
plt.plot(theta[0], theta[1], c='r', marker="x")
plt.pause(0.5)
plt.ioff()

input('ex1 Finished. Press ENTER to exit')


from __future__ import division
import numpy as np
import pylab as pl

one_by_nine = 1/9.0
nine_by_511 = 9/511.0
def getIest_Imp(N):
    y = np.random.random(N)
    # Inverse function calculated manually
    x = np.power(511*y + 1, one_by_nine)
    f = 2*np.power(x,8) -1
    w = nine_by_511 * np.power(x,8)
    Iest = np.mean(np.true_divide(f,w))
    return Iest

def getIest_Sm(N):
    # b = 2 and a = 1 Hence b-a = 1
    # which doesn't affect the integral
    # has been omitted from the calculations
    x = np.random.random(N)+1 # shift the rnadom values between 1 and 2
    f = 2*np.power(x,8)-1
    Iest = np.mean(f)
    return Iest

if __name__ == '__main__':
    np.random.seed(7777)
    exact = 1013/9.0
    Iest_Imp = []
    absErr_Imp = []
    Iest_Sm = []
    absErr_Sm = []
    Ns = map(lambda x: int(round(x)), np.logspace(2, 5, 50))
    for N in Ns:
        estImp = getIest_Imp(N)
        Iest_Imp.append(estImp)
        errImp = abs(exact-estImp)
        absErr_Imp.append(errImp)

        estSm = getIest_Sm(N)
        Iest_Sm.append(estSm)
        errSm = abs(exact-estSm)
        absErr_Sm.append(errSm)

        print "{} & {} & {} & {} & {} \\\\".format(N,estImp,errImp,estSm,errSm)

    pl.plot(Ns, Iest_Imp,label="Importance Sampling")
    pl.plot(Ns, Iest_Sm,label="Sample Mean")
    pl.plot(Ns, np.ones(len(Iest_Sm))*exact, label="Exact")
    pl.legend(framealpha=0.5)
    pl.xlabel("Ns")
    pl.ylabel("Integral")
    pl.savefig("Integrals.png")

    pl.figure()
    pl.loglog(Ns,absErr_Imp,label="Importance Sampling")
    pl.loglog(Ns,absErr_Sm,label="Sample Mean")
    pl.loglog(Ns,map(lambda x:1/(x**0.5),Ns),label="1/sqrt(N)")
    pl.legend(framealpha=0.5)
    pl.xlabel("Ns")
    pl.ylabel("Absolute Errors")
    pl.savefig("Errors.png")
    pl.show()


#!/bin/env python
"""
Smear 1D data of equidistance intervals with Gaussians.

Usage:
    gaussian_smear.py [options] INFILE

Options:
    -h, --help  Show this help messange and exit.
    -s, --sigma=SIGMA
                Width of Gaussian (sigma) in the unit of dx. [default: 2.0]
    -x=<x>      Position of x data (start from 1) [default: 1]
    -y=<y>      Position of y data (start from 1) [default: 1]
"""
from __future__ import print_function

import os,sys,math
import numpy as np
from docopt import docopt

def gsmear(xd,yd,sigma,ngwidth=3):
    """
    Compute Gaussian-smearing of given data with smearing width *sigma*.
    """
    dx= xd[1]-xd[0]
    sgm= sigma*dx
    pref= dx/(np.sqrt(2.0*np.pi)*sgm)
    ndat= len(xd)
    nwidth = int(sigma*ngwidth)
    #nwidth = ndat
    gdat= np.zeros(ndat,dtype=np.float)
    expfact = 1.0/sgm**2/2
    for ix in range(ndat):
        #gdat[ix]= yd[ix]
        for jx in range(-nwidth+1,nwidth):
            kx= ix+jx
            if kx < 0:
                kx = abs(kx)
            elif kx >= ndat:
                kx = 2*ndat -kx -1
            gdat[ix] += yd[kx]*pref*np.exp(-(dx*jx)**2*expfact)
    #gdat /= 2
    return gdat

def gsmear_file(infname,sigma,xp,yp):
    """
    Read data from the given file and pass data to `gsmear` method.
    """
    infile= open(infname,'r')
    nline= 0
    for line in infile.readlines():
        if line[0] == "#":
            continue
        nline += 1
    infile.seek(0)
    xd= np.zeros(nline,dtype=np.float)
    yd= np.zeros(nline,dtype=np.float)
    il= 0
    for line in infile.readlines():
        if line[0] == "#":
            continue
        sline= line.split()
        xd[il]= float(sline[xp])
        yd[il]= float(sline[yp])
        il += 1
    infile.close()
    xd,gdat= gsmear(xd,yd,sigma)
    return xd,gdat

if __name__ == "__main__":

    args= docopt(__doc__)
    xp= int(args['-x']) -1
    yp= int(args['-y']) -1
    sigma= float(args['--sigma'])
    infname= args['INFILE']

    xd,gdat= gsmear_file(infname,sigma,xp,yp)

    outfile= open(infname+'.smeared','w')
    for il in range(len(gdat)):
        outfile.write(' {0:15.2f} {1:15.7f}\n'.format(xd[il],gdat[il]))
    outfile.close()

    print(' write '+infname+'.smeared')
    print(' GAUSSIAN_SMEAR done ')


#-------------------------------------------------------------------------
# This pytest script contains tests for the optimization algorithms in the
# script Optimize.py
#-------------------------------------------------------------------------

#Import the relevant classes and modules
#from DreamDiff import DreamDiff as ad
#from DreamOptimize import Optimize
from DreamDiff.DreamDiff import DreamDiff as ad
from DreamDiff.DreamOptimize import Optimize

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

# Test 1: Newton's method
def test_Newton():

    assert (np.round(Optimize.newtons_method('x^2 - 1', 0.25, 0.0001, max_iters=5000)[0], 3) == 1.000)
    assert (np.round(Optimize.newtons_method('x^2 - 2', 2.0, 0.001, max_iters=500)[0], 3) == round(math.sqrt(2),3))
    assert (np.round(Optimize.newtons_method('x^3 - 3*x + 1', 2.0, 0.001, max_iters=500)[0], 3) == 1.532)

# Test 2: Gradient Descent
def test_GradDescent():

    assert (np.round(Optimize.grad_descent('x^2', 1.0, 0.0001, max_iters = 5000, eta = 0.5)[0], 3) == 0.00)
    assert (np.round(Optimize.grad_descent('x^2 - 1', 1, 0.0001, max_iters=5000, eta = 0.5)[0], 3) == round(0.000, 3))
    assert (np.round(Optimize.grad_descent('x^2 - 2', 2.0, 0.001, max_iters=5000, eta = 0.5)[0], 3) == round(0.000,3))

# Test 3: Nesterov Gradient Descent
def test_nesterov_grad_descent():

    assert (np.round(Optimize.nesterov_grad_descent('x^2', 1.0, 0.0001, max_iters = 5000, eta = 0.5)[0],3) == 0.00)
    assert (np.round(Optimize.nesterov_grad_descent('x^2 - 1', 1, 0.0001, max_iters=5000, eta = 0.5)[0], 3) == round(0.000, 3))
    assert (np.round(Optimize.nesterov_grad_descent('x^2 - 2', 2.0, 0.001, max_iters=5000, eta = 0.5)[0], 3) == round(0.000,3))

# Test 4: Quadratic Splines
def test_quadratic_spline():
    assert (int(abs(Optimize.quadratic_spline([2,3,4], [3,8,11])[0])) == 0)
    assert (int(Optimize.quadratic_spline([2,3,4,5,6], [3,8,11,14,18])[1]) == 5)

    with pytest.raises(Exception) as excinfo:
        Optimize.quadratic_spline([1,2], [10,15,20])
    assert "do not match" in str(excinfo.value)

    values = Optimize.quadratic_spline([2,3,4,5,6], [-3,-8,-11,-14,-18])
    assert (int(values[0]*4 + values[1]*3 + values[2]) == -8)

# Test 5: Plot Coefficients
def test_plot_coeffs():
    with pytest.raises(Exception) as excinfo:
        Optimize.plot_coeffs([-0.,  5.,  5., -0.,  5.,  5.], [1,2], [10,15,20])
    assert "do not match" in str(excinfo.value)

    #assert(type(Optimize.plot_coeffs([-0.,  5.,  5., -0.,  5.,  5.], [1,2,3], [10,15,20])) == plt)
    assert(Optimize.plot_coeffs([-0.,  5.,  5., -0.,  5.,  5.], [1,2,3], [10,15,20]) == True)

# Test 6: Animate Gradient Descent
def test_animate_gradient():
    f = 'tan(sin(x) + 3)'
    assert(Optimize.animate_grad_desc(f, 4, epsilon=0.00001, max_iters=500, eta=0.1, runtime=20, method='grad') == None)

# Test 7: Animate Newton's Method
def test_animate_newtons():
    f = 'x^3 - 3*x^2 + 4'
    assert(Optimize.animate_newtons(f, 0.3, epsilon=0.000001, max_iters=500, runtime=20) == None)


import numpy as np
import time

def selection_sort(x):
    for i in range(len(x)):
        swap = i + np.argmin(x[i:])
        (x[i], x[swap]) = (x[swap], x[i])
    return x

def k_near():
    # creating a random set of 10 points on a two-dimensional plane.
    x = np.random.rand(10, 2)
    # compute the distance between each pair of points.
    dist_sq = np.sum((x[:, np.newaxis, :] - x[np.newaxis, :, :]) ** 2, axis=-1)
    # for each pair of points, compute differences in their coordinates
    differences = x[:, np.newaxis, :] - x[np.newaxis, :, :]
    print('differences.shape', differences.shape)
    # square the coordinate differences
    sq_differences = differences ** 2
    print('sq_differences.shape', sq_differences.shape)
    # sum the coordinate differences to get the squared distance
    dist_sq = sq_differences.sum(-1)
    print('dist_sq.shape', dist_sq.shape)
    dist_sq.diagonal()
    nearest = np.argsort(dist_sq, axis=1)
    print(nearest)
    K = 2
    nearest_partition = np.argpartition(dist_sq, K + 1, axis=1)
    print('nearest_partition', nearest_partition)

def fast_sort():
    a = np.array([1, 3, 2, 7, 10, 5, 9, 8, 6, 4])
    print('a = ', a)
    # a.sort()
    # print('after a.sort(): ', a)
    i = np.argsort(a)
    print('after argsort(a) ', a)
    print('indice : ', i)
    print('a[i] = ', a[i])

    x = np.random.randint(0, 10, (4, 6))
    print('x = ', x)
    print('np.sort(x, axis=0) ', np.sort(x, axis=0))
    print('np.sort(x, axis=1)', np.sort(x, axis=1)) # sort each column of X
    print('after x = ', x)

def part_sort():
    x = np.array([7, 2, 3, 8, 6, 5, 4, 0, 9, 10])
    print('np.partition(x, 3):', np.partition(x, 3))
    print('np.partition(x, 5):', np.partition(x, 5))
    print('x = ', x)
    y = np.random.randint(0, 10, (5, 5))
    print('np.partition(y, 2, axis=0)', np.partition(y, 2, axis=0))
    print('np.partition(y, 2, axis=1)', np.partition(y, 2, axis=1))
    print('y =', y)

def bogo_sort(x):
    while np.any(x[:-1] > x[1:]):
        np.random.shuffle(x)
    return x

if __name__ == '__main__':
    print('Numpy Version:', np.__version__)
    # fast_sort()
    # part_sort()
    k_near()


"""
July 01, 2019.
Luis Da Silva.
luisdanield@gmail.com

This is an implementation of value iteration for finding a tabular solution.

A gambler is offered unlimited coin flips with a coin with probability p of success.
Its objective is to reach 100$.
He sets the value of his bets. If he looses then the bet amount is lost, otherwise he doubles his money.
Find an optimal solution given the capital he has.
"""

import numpy as np
import matplotlib.pyplot as plt

def expected_return(state, action, state_value, p):
    reward = 0
    next_state_value = 0

    # Evaluate positive case
    new_state_positive = state + action
    if new_state_positive >= 100:
        reward = p
    else:
        idx = int(new_state_positive - 1)
        next_state_value += state_value[idx] * p

    # Evaluate negative case
    new_state_negative = state - action
    if new_state_negative > 0:
        idx = int(new_state_negative - 1)
        next_state_value += state_value[idx] * (1-p)

    return reward + next_state_value

def gamble(p, goal, tolerance=1e-1):
    actions = np.linspace(1, goal-1, goal-1)
    policy = np.ones_like(actions, dtype=int)
    state_value = np.zeros_like(actions)

    iter = 0
    while True:
        iter += 1
        old_state_value = state_value.copy()
        old_policy = policy.copy()

        # Evaluate policy
        for state in range(1, state_value.shape[0]):
            state_value[state] = expected_return(state, policy[state], state_value, p)

        # Improve policy
        for state in range(1, state_value.shape[0]):
            rewards = []
            for action in actions:
                if action > state:
                    rewards.append(-np.inf)
                else:
                    rewards.append(expected_return(state, action, state_value, p))
            policy[state] = actions[np.argmax(rewards)]

        change = np.abs(state_value - old_state_value).max()
        policy_stable = (old_policy == policy).all()
        print(f'Iter {iter} finished! SV change: {change}. Policy stable: {policy_stable}.')
        if change <= tolerance and policy_stable:
            break

    return policy, state_value

if __name__ == '__main__':
    p = 0.45
    policy, state_value = gamble(p=p, goal=100, tolerance=1e-5)

    plt.plot(policy)
    plt.title('Policy')
    plt.xlabel('Money')
    plt.ylabel('Gamble')
    plt.savefig(f'graphs/gamblers_problem_policy_p{p}.png')
    plt.show()

    plt.plot(state_value)
    plt.axvline(p*100, 0, 1, color='black', ls='--')
    plt.title('State Value')
    plt.xlabel('Money')
    plt.ylabel('Probability of succeed')
    plt.savefig(f'graphs/gamblers_problem_state_value_p{p}.png')
    plt.show()


import numpy as NP
import scipy as SP
import scipy.signal
import pylab as PL

def pzplot(b,
           a,
           ax=None,
           c='C0',
           guide_opts={'color':  '0.8',
                       'ls':     '--',
                       'zorder': -10}):
    """
    Create pole-zero plot of the rational transfer function defined by
    the polynomial coefficients *b* and *a*. Plot in axis *ax* (or
    create a new axis if `None`).  Plot poles and zeros in color
    *c*. Use the plot options *guide_opts* to style the unit circle
    and real and imaginary axis lines. Return the tuple containing the
    tuple of zeros, poles, and gain (see :func:`scipy.signal.tf2zpk`)
    and the axis *ax*.
    """
    if ax is None:
        ax = PL.subplot(111)
    z, p, k = SP.signal.tf2zpk(b, a)
    ax.add_patch(PL.Circle((0, 0), 1, fill=False, **guide_opts))
    ax.axhline(0, **guide_opts)
    ax.axvline(0, **guide_opts)
    ax.scatter(NP.real(z),
               NP.imag(z),
               marker=PL.matplotlib.markers.MarkerStyle('o', 'none'),
               facecolors='none',
               edgecolors=c)
    ax.scatter(NP.real(p),
               NP.imag(p),
               marker='x',
               color=c)
    xlim = PL.xlim()
    PL.xlim(xmin=max(xlim[0], -1.1))
    PL.xlim(xmax=max(xlim[1],  1.1))
    ylim = PL.ylim()
    PL.ylim(ymin=max(ylim[0], -1.1))
    PL.ylim(ymax=max(ylim[1],  1.1))
    ax.set_aspect('equal')
    PL.xlabel('Real axis')
    PL.ylabel('Imaginary axis')
    return (z, p, k), ax


# coding: utf-8

# In[1]:

import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt

# In[2]:

# Linear line
# x_vals = np.linspace(start=0, stop=5, num=50)
# y_vals = 2 * x_vals + 1
# input_shape = 1

# Line with noise
sigma = 5
x_vals = np.linspace(start=0, stop=5, num=50)
y_vals = 2 * x_vals + 1 + sigma* np.random.randn(50)
input_shape = 1

# In[3]:

plt.plot(x_vals, y_vals, 'r')
plt.show()

# In[4]:

def visualize_line(w_val):
    x_grid = np.linspace(start=0, stop=5, num=50)
    y_guessed = w_val[0] * x_grid + w_val[1]

    plt.plot(x_grid, y_guessed, 'b')
    plt.plot(x_vals, y_vals, 'r')

    plt.ylim((np.min(y_vals),np.max(y_vals)))
    plt.xlim((0,5))

    plt.show()

# In[5]:

x_tf = tf.placeholder(tf.float64, [])
y_tf = tf.placeholder(tf.float64, [])

w = np.zeros([2])
w_tf = tf.Variable(initial_value=w, dtype=tf.float64)

# In[6]:

yhat_tf =  tf.reduce_sum(w_tf[0] * x_tf) + w_tf[1]
loss = 1/2. * (y_tf - yhat_tf) ** 2

# In[7]:

lr = 0.001
optimization = tf.train.GradientDescentOptimizer(learning_rate=lr).minimize(loss)

# In[8]:

sess = tf.Session()
init_op = tf.global_variables_initializer()
sess.run(init_op)

# In[9]:

epochs = 15
for ee in range(epochs):
    epoch_loss = 0.
    for ii in range(x_vals.shape[0]):
        x_i = x_vals[ii]
        y_i = y_vals[ii]

        run_dict = {'optimization': optimization, 'loss':loss}
        feed_dict = {x_tf:x_i, y_tf:y_i}
        out_dict = sess.run(run_dict, feed_dict=feed_dict)
        epoch_loss += out_dict['loss']

        # w_trained = sess.run(w_tf)
        # print('Current loss: %.5f' %  out_dict['loss'])
        # visualize_line(w_trained)

    w_trained = sess.run(w_tf)
    print('Epoch loss: %.5f' % epoch_loss)
    visualize_line(w_trained)

# In[10]:

print('w: %.2f, b: %.2f' % (w_trained[0], w_trained[1]))


"""
Simple implementation of Fisher Discriminant Analysis
Demo with 2D toy data

Author: Duong Nguyen @TokyoTech
Contact: nguyen@sg.cs.titech.ac.jp
"""

import numpy as np
import matplotlib.pyplot as plt
from scipy.linalg import eig # for generalized eigensystem solver
from mpl_toolkits.mplot3d import Axes3D # for 3d plot

#------------------------------------------#
#    Load data from file, plotting code    #
#------------------------------------------#
def loadData(filename, label):
    """ Load data from file.
        Assign given label to each samples.

        Returns:
        ----------------------
        X: n x d matrix of n samples
        Y: n x 1 label vector
        n_samples: number of samples
        dim: data dimension
    """
    X = []
    with open(filename, 'r') as fin:
        for line in fin:
            row = map(float, line.strip().split(','))
            X.append(row)

    n_samples = len(X)
    dim = len(X[0])
    Y = [label] * n_samples
    X = np.asarray(X, dtype='float64')
    Y = np.asarray(Y, dtype='int16')
    return X, Y, n_samples, dim

def plot_2d_xx(infile1, infile2, outfile=None, show=True):
    """ Plot 2d data. Just for testing."""
    X1, Y1, n1, d1 = loadData(infile1, 0)
    X2, Y2, n2, d2 = loadData(infile2, 1)
    d1 = X1.shape[1]
    d2 = X2.shape[1]
    assert d1 == d2, "Dimension not match!"
    assert d1 == 2, "2D!"

    plt.plot(X1[:,0], X1[:,1], 'rx', label='Class 1')
    plt.plot(X2[:,0], X2[:,1], 'go', label='Class 2')
    plt.legend(loc='best', prop={'size':20})

    if outfile: # save to file
        plt.savefig(outfile)
    if show: # show figure
        plt.show()

#----------------#
#    FDA code    #
#----------------#
def FDA(X, Y, n_class, m):
    """ Fisher Discriminant Analysis.
        Params:
        -------------
        X: n x d matrix of samples
        Y: n x 1 label vector
        n_class: number of classes
        m: reduced dimensionality

        Returns:
        ---------------
        B_FDA: m x d matrix (FDA embedding matrix)
    """
    n, d = X.shape

    nc = [] # number of samples from each class
    muc = [] # list of class sample means
    for i in range(n_class):
        nc.append(len(Y[Y==i]))
        muc.append(np.mean(X[Y==i], 0))

    mu_X = np.mean(X, 0) # sample mean of the whole data

    # Compute Sb
    Sb = np.zeros((d,d), dtype='float64')

    for i in range(n_class):
        Sb += nc[i] * np.dot(np.reshape(muc[i]-mu_X, (d,1)), np.reshape(muc[i]-mu_X, (1,d)))

    # compute Sw
    Sw = np.zeros((d,d), dtype='float64')
    for i in range(n_class):
        Sw += np.dot((X[Y==i]-muc[i]).T, (X[Y==i]-muc[i]))

    eigvals, V = eig(Sb, Sw)
    sorted_indices = np.argsort(eigvals)[::-1]
    V = V[:, sorted_indices] # sort in decreasing order of eigenvalues
    return V[:, 0:m] # return the m largest component

def testFDA(outfile='fda-2d-L3.png', show=True, debug=False):
    """ Test FDA."""
    X1, Y1, n1, d1 = loadData('2d-L3-c1.txt', 0)
    X2, Y2, n2, d2 = loadData('2d-L3-c2.txt', 1)

    assert d1 == d2, "Dimensions must match!"

    X = np.vstack((X1, X2))
    Y = np.hstack((Y1, Y2))
    fda_dir = FDA(X, Y, n_class=2, m=1)

    if debug: # print fda_dir in debug mode
        print fda_dir

    x_mean = np.mean(X, 0)

    plt.plot(X1[:,0], X1[:,1], 'rx', markersize=10, mew='2', label='Class 1')
    plt.plot(X2[:,0], X2[:,1], 'bo', markersize=10, mew='2', mfc='w', mec='b', label='Class 2')

    plt.plot([x_mean[0] + k*fda_dir[0] for k in np.linspace(-9,9)],
                [x_mean[1] + k*fda_dir[1] for k in np.linspace(-9,9)],
                'k-', lw=4, label='FDA')

    plt.legend(loc='best', prop={'size':20})
    plt.axis('equal')
    plt.savefig(outfile)
    if show:
        plt.show()

if __name__ == '__main__':
    testFDA()


r"""
Solve Poisson equation in 1D with homogeneous Neumann bcs

    \nabla^2 u = f

Use Shen's Neumann basis

The equation to solve is

     (\nabla^2 u, v) = (f, v)

"""
import sys
import os
import sympy as sp
import numpy as np
from shenfun import inner, div, grad, TestFunction, TrialFunction, FunctionSpace, \
    Array, Function, legendre, chebyshev, extract_bc_matrices, la, SpectralMatrix, dx

# Collect basis from either Chebyshev or Legendre submodules
assert len(sys.argv) == 3, "Call with two command-line arguments"
assert sys.argv[-1].lower() in ('legendre', 'chebyshev')
assert isinstance(int(sys.argv[-2]), int)
family = sys.argv[-1].lower()
Solver = chebyshev.la.Helmholtz if family == 'chebyshev' else la.SolverGeneric1ND

# Use sympy to compute a rhs, given an analytical solution
x = sp.symbols("x", real=True)
alpha = 0
ue = sp.cos(2*sp.pi*x)
#ue = sp.cos(5*sp.pi*(x+0.1)/2)
fe = -ue.diff(x, 2)+alpha*ue

# Size of discretization
N = int(sys.argv[-2])

bc = {'left': ('N', ue.diff(x, 1).subs(x, -1)), 'right': ('N', ue.diff(x, 1).subs(x, 1))}
SD = FunctionSpace(N, family=family, bc=bc, basis='ShenNeumann')
u = TrialFunction(SD)
v = TestFunction(SD)

# Get f on quad points
fj = Array(SD, buffer=fe)

# Compute right hand side of Poisson equation
f_hat = inner(v, fj)

# Get left hand side of Poisson equation
A0 = inner(v, div(grad(u)))
B0 = inner(v, u)

# Solve
u_hat = Function(SD).set_boundary_dofs()
M = -A0
if alpha != 0:
    M += alpha*B0

# The coefficient matrix is singular if alpha=0. In that case add constraint
constraint = ((0, dx(Array(SD, buffer=ue), weighted=True)/dx(Array(SD, val=1), weighted=True)),) if alpha == 0 else ()

if alpha != 0:
    # Use Helmholtz solver
    sol = Solver(A0, B0, -1, alpha)
    u_hat = sol(f_hat, u_hat, constraints=constraint)
else:
    u_hat = M.solve(f_hat, u_hat, constraints=constraint)

# Transform to real space
uj = u_hat.backward()

# Compare with analytical solution
ua = Array(SD, buffer=ue)
print(abs(uj-ua).max())
assert np.allclose(uj, ua)

if 'pytest' not in os.environ:
    import matplotlib.pyplot as plt
    plt.figure()
    X = SD.mesh()
    plt.plot(X, uj)

    plt.figure()
    plt.plot(X, ua)

    plt.figure()
    plt.plot(X, ua-uj)
    plt.title('Error')
    #plt.show()


import numpy as np

def generate_regression_data(degree, N, amount_of_noise=1.0):
    """
    Generates data to test one-dimensional regression models.

    Args:
        degree (int): degree of polynomial that relates the output x and y
        N (int): number of points to generate
        amount_of_noise (float): amount of random noise to add to the relationship between x and y.

    Returns:
        x (np.ndarray): explanatory variable of size N, ranges between -1 and 1.
        y (np.ndarray): response variable of size N, which responds to x as polynomial of degree 'degree'.
    """

    # Generate explanatory variable x of floats chosen are random between -1 and 1
    x = np.zeros((N,), dtype=float)
    iteration = 0
    for i in x:
        x[iteration] = np.random.uniform(-1.0, 1.0)
        iteration += 1

    # Generate polynomial float coefficients chosen uniformally at random between -10 and 10
    exps = np.arange(degree+1)
    coeff = np.zeros((degree+1,), dtype=float)
    j = 0
    for i in coeff:
        coeff[j] = np.random.uniform(-10.0, 10.0)
        j += 1

    # Generate response variable y that contains f(x)
    y = np.zeros(len(x))
    f = 0
    for i in x:
        y[f] = sum(coeff[a]*x[f]**exps[a] for a in range(len(coeff)))
        f += 1

    # Add Gaussian noise n to y with mean = 0.0 and standard deviation
    std_y = np.std(y)
    noise = np.random.normal(loc=0.0, scale=amount_of_noise*std_y, size=y.shape)
    y_noise = y + noise

    return x, y_noise


import numpy as np

def triangular_superior(A, b):
    """Resolve um sistema linear com matriz de coeficientes \
triangular superior.

    Parâmetros:
        [A] (numpy.array): Matriz triangular superior (coeficientes).
        [b] (numpy.array): Vetor das constantes.

    Retorno:
        Vetor com a solução (numpy.array)
"""

    n = len(A)
    x = np.zeros(n)

    x[n - 1] = b[n - 1] / A[n - 1, n - 1]

    for k in range(n - 2, -1, -1):
        s = 0
        for j in range(k + 1, n):
            s += A[k, j] * x[j]
            x[k] = (b[k] - s) / A[k, k]

    print(f"A solução do sistema é o vetor: {x}")
    return x

if __name__ == "__main__":
    A = np.array([[2, 1, 3], [0, 1, -1], [0, 0, 2]])
    b = np.array([11, 1, 4])
    triangular_superior(A, b)


import numpy as np

### Functions for you to fill in ###

# pragma: coderesponse template

def polynomial_kernel(X, Y, c, p):
    """
        Compute the polynomial kernel between two matrices X and Y::
            K(x, y) = (<x, y> + c)^p
        for each pair of rows x in X and y in Y.

        Args:
            X - (n, d) NumPy array (n datapoints each with d features)
            Y - (m, d) NumPy array (m datapoints each with d features)
            c - a coefficient to trade off high-order and low-order terms (scalar)
            p - the degree of the polynomial kernel

        Returns:
            kernel_matrix - (n, m) Numpy array containing the kernel matrix
    """
    kernel_matrix = (X.dot(Y.T) + c)**p

    return kernel_matrix
# pragma: coderesponse end

# pragma: coderesponse template

def rbf_kernel(X, Y, gamma):
    """
        Compute the Gaussian RBF kernel between two matrices X and Y::
            K(x, y) = exp(-gamma ||x-y||^2)
        for each pair of rows x in X and y in Y.

        Args:
            X - (n, d) NumPy array (n datapoints each with d features)
            Y - (m, d) NumPy array (m datapoints each with d features)
            gamma - the gamma parameter of gaussian function (scalar)

        Returns:
            kernel_matrix - (n, m) Numpy array containing the kernel matrix
    """
    n, d = X.shape
    m = Y.shape[0]

    # Naive version with for loops
#    kernel_matrix = np.zeros((n,m))
#
##### Single for loop ####
#    for i in range(n):
#        d = X[i,:] - Y  # Using numpy broadcasting to get differences
#        b = np.sum(d**2, axis=1)
#        kernel_matrix[i,:] = np.exp(-gamma*b)
#### End: single-loop version ####

#### Vectorized version (runs slower than the single loop version) ####
#    kernel_matrix = np.linalg.norm((X[:,None] - Y), ord=2, axis=2)**2
#    kernel_matrix = (np.sum(X**2, axis=1)[:,None] + np.sum(Y**2, axis=1)) - 2*(X @ Y.T)
    kernel_matrix = X**2 @ np.ones((d,m)) + np.ones((n,d)) @ Y.T**2 - 2*(X @ Y.T)
    kernel_matrix = np.exp(-gamma*kernel_matrix)
#### End: vectorized version ####

    return kernel_matrix
# pragma: coderesponse end


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

def online_p4():
    d_vc = 50
    delta = 0.05
    N = 5
    def m_H(n):
        return n ** d_vc

    a_bound = math.sqrt((8/N) * math.log((4*m_H(2*N))/delta))
    b_bound = math.sqrt(2 * math.log(2*N*m_H(N))/N) + math.sqrt((2/N) * math.log(1/delta)) + 1/N
    c_bound = math.sqrt((1/N) * math.log(6 * m_H(2*N) / delta) + 1/(N**2)) + 1/N
    d_bound = math.sqrt((1/(2*N - 4)) * (math.log(4/delta) + 2*d_vc*math.log(N)) + (1/(N-2))**2) + 1/(N-2)
    e_bound = math.sqrt((16/N) * math.log(2 * m_H(N) / math.sqrt(delta)))

    print("a: ", a_bound)
    print("b: ", b_bound)
    print("c: ", c_bound)
    print("d: ", d_bound)
    print("e: ", e_bound)

def get_data(path):
    data_all = np.genfromtxt(path)
    data_x = data_all[:, :-1]
    data_y = data_all[:, -1]
    return data_x, data_y

def error(pred, gt):
    return np.sum(pred != gt) / len(gt)

def decision_stump(data_x, data_y):
    """
    x, y are both in shape (data_num, )
    Return (theta, s= +/-1)
    """
    data_len = len(data_x)
    sort_arg = np.argsort(data_x)
    data_x = data_x[sort_arg]
    data_y = data_y[sort_arg]
    thetas = [(data_x[i] + data_x[i+1]) / 2 for i in range(data_len-1)]
    thetas.append(data_x[0] - 1)
    stump = (None, None)
    error_min = 1
    for theta in thetas:
        pred = np.ones(data_len) * (-1)
        pred[data_x > theta] = 1
        err = error(pred, data_y)
        if  err < error_min:
            error_min = err
            stump = (theta, 1)
        pred = np.ones(data_len) * (-1)
        pred[data_x < theta] = 1
        err = error(pred, data_y)
        if  err < error_min:
            error_min = err
            stump = (theta, -1)
    return stump

def online_p19_p20():
    train_x, train_y = get_data("train.dat")
    test_x , test_y  = get_data("test.dat")
    train_len, test_len = len(train_y), len(test_y)

    dim = None
    stump = None
    E_in = 1
    for d in range(train_x.shape[1]):
        ds = decision_stump(train_x[:, d], train_y)
        pred = np.ones(train_len) * (ds[1])
        pred[train_x[:, d] < ds[0]] *= (-1)
        err = error(pred, train_y)
        if err < E_in:
            E_in = err
            dim = d
            stump = ds

    test_pred = np.ones(test_len) * stump[1]
    test_pred[test_x[:, dim] < stump[0]] *= (-1)
    E_out = error(test_pred, test_y)

    print("E in:  {}".format(E_in))
    print("E_out: {}".format(E_out))

def E_out(s, theta):
    return 0.5 + 0.3 * s * (min(abs(theta), 1) - 1)

def plot_hist(data_size, fig_name):
    error_distance = []
    error_in  = []
    error_out = []
    for _ in range(1000):
        x = np.random.rand(data_size) * 2 - 1
        y = np.ones(data_size)
        y[x < 0] = -1
        noise_idx = np.random.choice(data_size, int(0.2 * data_size), replace= False)
        y[noise_idx] *= -1

        theta, s = decision_stump(x, y)
        pred = np.ones(data_size) * s
        pred[x < theta] *= (-1)
        e_in  = error(pred, y)
        e_out = E_out(s, theta)
        e_diff = e_in - e_out
        error_distance.append(e_diff)
        error_in.append(e_in)
        error_out.append(e_out)

    print("E_in: {}".format(np.mean(error_in)))
    print("E_out: {}".format(np.mean(error_out)))
    plt.title("E_in: {:.3f} E_out: {:.3f}".format(np.mean(error_in), np.mean(error_out)))
    plt.hist(error_distance)
    plt.savefig(fig_name)
    plt.close()

def hw_p7_p8():
    plot_hist(20, "imgs/p7.png")
    plot_hist(2000, "imgs/p8.png")

def test():
    x, y = get_data("test.dat")
    print(x.shape)
    print(y.shape)

if __name__ == "__main__":
    hw_p7_p8()


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

import os

import numpy as np
import tensorflow as tf

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'

#
# voector
#

vector = np.random.randint(1, 10, (2, 3)).astype(np.float32)
vector_1 = vector[0]
vector_2 = vector[1]
print(vector_1, vector_2)

# length
# https://www.tensorflow.org/api_docs/python/tf/norm
length_11 = tf.norm(vector_1)
print(length_11)
length_21 = tf.norm(vector_2)
print(length_21)

# sqrt(sum(square(x)))
length_12 = np.sqrt(np.sum(np.square(vector_1)))
print(length_12)

length_22 = np.sqrt(np.sum(np.square(vector_2)))
print(length_22)

#
# cosine sim by dot
#

# a.b/|a||b|
output_1 = tf.matmul([vector_1], [vector_2], transpose_b=True) / (length_11 * length_21)
print(output_1)

#
# cosine sim by normalize and dot
#

# normalize vector_1
normal_11 = vector_1 / length_11
print(normal_11)
print(tf.norm(normal_11))

# normalize vector_1
# https://www.tensorflow.org/api_docs/python/tf/math/l2_normalize
normal_12 = tf.math.l2_normalize(vector_1)
print(normal_12)
print(tf.norm(normal_12))

# normalize vector_2
normal_21 = vector_2 / length_21
print(normal_21)
print(tf.norm(normal_21))

# normalize vector_2
normal_22 = tf.math.l2_normalize(vector_2)
print(normal_22)
print(tf.norm(normal_22))

output_2 = tf.matmul([normal_11], [normal_21], transpose_b=True)
print(output_2)


import numpy as np
'''感知机逻辑门实现'''

def AND(x1, x2):
    '''与门'''
    x = np.array([x1, x2])
    w = np.array([0.5, 0.5])
    b = -0.7
    tmp = np.sum(w*x) + b
    if tmp <= 0:
        return 0
    else:
        return 1

def NAND(x1, x2):
    '''与非门'''
    x = np.array([x1, x2])
    w = np.array([-0.5, -0.5])
    b = 0.7
    tmp = np.sum(w*x) + b
    if tmp <= 0:
        return 0
    else:
        return 1

def OR(x1, x2):
    '''或门'''
    x = np.array([x1, x2])
    w = np.array([0.5, 0.5])
    b = -0.2
    tmp = np.sum(w*x) + b
    if tmp <= 0:
        return 0
    else:
        return 1

def XOR(x1, x2):
    '''异或门'''
    s1 = NAND(x1, x2)
    s2 = OR(x1, x2)
    y = AND(s1, s2)
    return y

def step_function(x):
    '''阶跃函数'''
    return np.array(x > 0, dtype = np.int)

def sigmoid(x):
    '''针对二元分类问题的激活函数'''
    return 1/(1 + np.exp(-x))

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

def identity_function(x):
    '''恒等函数'''
    return x

def softmax(a):
    '''针对多元分类问题的激活函数'''
    c = np.max(a)
    exp_a = np.exp(a - c)    #溢出策略
    sum_exp = np.sum(exp_a)
    y = exp_a / sum_exp

    return y

def mean_square_error(y, t):
    '''均方误差'''
    return 0.5 * np.sum((y - t) ** 2)

def cross_entropy_error(y, t):
    '''交叉熵误差'''
    delta = 1e-7
    return -np.sum(t * np.log(y + delta))

def cross_entropy_error_onehot(y, t):
    if y.ndim == 1:
        t = t.reshape(1, t.size)
        y = y.reshape(1, y.size)

    batch_size = y.shape[0]
    return -np.sum(t * np.log(y + 1e-7)) / batch_size

def cross_entropy_error_not_onehot(y, t):
    if y.adim == 1:
        t = t.reshape(1, t.size)
        y = y.reshape(1, y.size)

    batch_size = y.shape[0]
    return -np.sum(np.log(y[np.arange(batch_size,), t] + 1e-7)) / batch_size

def numerical_diff(f, x):
    '''数值微分函数'''
    h = 1e-4
    return (f(x+h) - f(x-h)) / (2 * h)


import os

import numpy as np
import pandas as pd
import typer
from sklearn.decomposition import PCA

def _dimension_reduction(percentage_variance: list, variance_explained: int):
    cumulative_variance = 0
    n_components = 0
    while cumulative_variance < variance_explained:
        cumulative_variance += percentage_variance[n_components]
        n_components += 1
    return n_components

def pca_variance(
    filepath: str = typer.Option(..., help="Name of the csv file"),
    delimiter: str = typer.Option(..., help="Delimetr of the csv file"),
    variance_explained: int = typer.Option(
        ...,
        help="""The total variace that is want it to be explained by the Principal Components.
                Not needed if we set the number of components. Default to 75.""",
    ),
):
    os.chdir("data")

    data = pd.read_csv(str(filepath), sep=delimiter, decimal=".")

    variance_explained = int(variance_explained)

    corr = data.corr().round(2)
    corr.to_csv("correlation_matrix_heatmap.csv", sep=delimiter)

    pca = PCA()
    pca_data = pca.fit_transform(data)
    per_var = np.round(pca.explained_variance_ratio_ * 100, decimals=1)
    np.savetxt("scree_plot.csv", per_var, delimiter=delimiter)

    number_components = _dimension_reduction(per_var, variance_explained)

    pca = PCA(number_components)
    pca_data = pca.fit_transform(data)
    pc_labels = ["PC" + str(x) for x in range(1, number_components + 1)]
    pca_df = pd.DataFrame(data=pca_data, columns=pc_labels)

    pca_df.to_csv("PCA_plot.csv", sep=delimiter, index=False)

    col = []
    for columns in np.arange(number_components):
        col.append("PC" + str(columns + 1))

    loadings = pd.DataFrame(pca.components_.T, columns=col, index=data.columns)
    loadings.to_csv("covariance_matrix.csv", sep=delimiter, index=True)

if __name__ == "__main__":
    typer.run(pca_variance)


"""
This code implements a perceptron algorithm (PLA).
First, we visualise the dataset which contains 2 features. We can see that the dataset can be clearly separated by drawing a straight line between them. The goal is to write an algorithm that finds that line and classifies all of these data points correctly.

The output file (e.g. 'output1_f.csv') contains the values of w1, w2 and b which define the 'threshold' line. The last row will be the most accurate one. Each time it goes through each of the examples in 'input1.csv', it adds a new line to the output file containing a comma-separated list of the weights w_1, w_2, and b (bias) in that order.

Upon convergence, the program stops, and the final values of w_1, w_2, and b are printed to the output file (output1.csv). This defines the decision boundary that your PLA has computed for the given dataset.

Note: When implementing your PLA, in case of tie (sum of w_jx_ij = 0), please follow the lecture note and classify the datapoint as -1.

Ensure this file can be executed as:
$ python3 problem1.py input1.csv output1.csv

The code includes plotting functions. However those are disabled when executing the code from the command line in the format specified immediately above.

"""

# builtin modules
import os
import psutil
import requests
import sys

# 3rd party modules
import pandas as pd
import numpy as np
import plotly.graph_objects as go

class problem1:

    def get_data(source_file, names_in:list = ['feature1','feature2','labels']):

        # Define input and output filepaths
        input_path = os.path.join(os.getcwd(),'datasets','in', source_file)

        # Read input data
        df = pd.read_csv(input_path, names=names_in)

        return df

    def perceptron_classify(df, n:int = 200, names_in:list = ['feature1','feature2','labels']):
        """
        1. set b = w = 0
        2. for N iterations, or until weights do not change
            (a) for each training example xᵏ with label yᵏ
                i. if yᵏ — f(xᵏ) = 0, continue
                ii. else, update wᵢ, △wᵢ = (yᵏ — f(xᵏ)) xᵢ
        """

        # transform the dataframe to an array
        data = np.asmatrix(df, dtype = 'float64')

        # get the first two columns as pairs of values
        features = data[:, :-1]
        # get the last column
        labels = data[:, -1]

        # assign zero weight as a starting point to features and labels
        w = np.zeros(shape=(1, features.shape[1]+1)) #e.g. array([0., 0., 0.])
        w_ = np.empty(shape=[0,3]) # declare w_ as an empty matrix of same shape as w

        for iteration in range(0,n):
            for x, label in zip(features, labels):
                x = np.insert(x, 0, 1) # add a column of 1s to represent w0
                f = np.dot(w, x.transpose()) # a scalar
                if f * label <= 0:
                    w += (x * label.item(0,0)).tolist() # because label comes from being a matrix (matrix([[1.]])) and needs to be converted to scalar
                else:
                    iteration = n

            w_ = np.vstack((w_, w))

        return (w_, w_[-1])

    def plot_results(df, weights, names_in:list = ['feature1','feature2','labels']):
        """
        Plot the Perceptron classifier, from the following inputs:
        - source_file: csv file with the input samples
        - weights: from perceptron_classify function
        - names_in: a list of the names of the columns (headers) in the input df
        returns:
        - a plot of the figure in the default browser, and
        - a PNG version of the plot to the "images" project directory
        """
        # Create the figure for plotting the initial data
        fig = go.Figure(data=go.Scatter(x=df[names_in[0]],
                                        y=df[names_in[1]],
                                        mode='markers',
                                        marker=dict(
                                        color=df[names_in[2]],
                                        colorscale='Viridis',
                                        line_width=1,
                                        size = 16),
                                        text=df[names_in[2]], # hover text goes here
                                        showlegend=False))  # turn off legend only for this item

        # Create the 1D array for X values from the first feature; this is just to be able to plot a line
        # within the space defined by the two features explored
        X = np.linspace(0, max(df[names_in[0]].max(),df[names_in[1]].max()))
        # Vector Y will calculated from the weights, w1, w2, the bias, b, and the value of X in its 1D linear space
        Y = []

        for b, w1, w2 in [weights]: #(matrix.tolist()[0] for matrix in weights):
            for x in X:
                if w2 == 0:
                    y = 0.0
                else:
                    y = (-(b / w2) / (b / w1))* x + (-b / w2) # per the equation of a line, e.g. C = Ax + By
                Y.append(y)

        # Add the threshold line to the plot
        fig.add_trace(go.Scatter(x=X, y=Y,
                                    mode= 'lines',
                                    name = 'Threshold'))

        # Give the figure a title
        fig.update_layout(title='Perceptron Algorithm | Problem 1')

        # Show the figure, by default will open a browser window
        fig.show()

        # export plot to png file to images directory
        # create an images directory if not already present
        if not os.path.exists("images"):
            os.mkdir("images")
        ## write the png file with the plot/figure
        return fig.write_image("images/fig1.png")

    def write_csv(filename, weights):
        # write the outputs csv file
        filepath = os.path.join(os.getcwd(),'datasets','out', filename)
        dataframe = pd.DataFrame(data=weights, columns=('b','w1','w2'))
        # reorder the columns in the dataframe in accordance with assignment
        order = [1,2,0] # setting column's order, 'b' goes as first column followed by weights
        dataframe = dataframe[[dataframe.columns[i] for i in order]]
        dataframe.to_csv(filepath)
        return print("New Outputs file saved to: <<", filename, ">>", sep='', end='\n')

    def main():

        in_data = 'input1.csv'
        out_data = 'output1.csv'

        df = get_data(in_data)
        (w_, w) = perceptron_classify(df)
        plot_results(df, w)
        write_csv(out_data, w_)

    if __name__ == '__main__':

        main()


import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from scipy.stats import multivariate_normal
import matplotlib
import time
import random
import math

Z1=[]
Z2=[]

#------------generate 1000 values for Z1 and Z2 to get ~N(0,1)------------------------#
def Marsaglia_and_Bray():
    count_acc=0
    while(1):
        u1=random.uniform(0,1)
        u2=random.uniform(0,1)
        u1=2*u1-1
        u2=2*u2-1
        x=u1**2+u2**2
        if(x>1):
            continue
        else:
            count_acc=count_acc+1
            y=math.sqrt(-2*math.log(x)/x)
            z1=u1*y
            z2=u2*y
            Z1.append(z1)
            Z2.append(z2)
            if(count_acc==1000):
                break
#--------------------------------------------------------------------------------------#

#-------------------find the matrix A from sigma1, sigma2 and rho----------------------#
def return_A(sigma1, sigma2, rho):
    A=[]
    A.append(sigma1) #A11
    A.append(0) #A12
    A.append(rho*sigma2) #A21
    A.append(sigma2*(math.sqrt(1-rho**2))) #A22
    return A

#--------------------------------------------------------------------------------------#

#--------------------------- PDF for multivariate normal-------------------------------#
def return_multivariate_normal_pdf(x,det,inv,mean):
    d=2
    diff=x-mean
    denom=(((2*math.pi)**(1/2))*(det**(1/2)))
    power_quan=-0.5*np.matmul(diff.T,np.matmul(inv,diff))
    num=math.exp(power_quan)
    res=num/denom
    return res
#--------------------------------------------------------------------------------------#

#--------------------------- PDF for univariate normal-------------------------------#
def return_univariate_normal_pdf(x,mean,var):
    power_term = -(np.square(x-mean))/(2*var)
    num=np.exp(power_term)
    denom = np.sqrt(2*np.pi*var)
    res=num/denom
    return res
#--------------------------------------------------------------------------------------#

a_values=[-0.5,0,0.5,1] # allowed values of a as per q1.1

# -----------------------values obtained from the Covariance Matrix E-----------------#
MU=[5,8]
SIGMA1=1
SIGMA2=2
#-------------------------------------------------------------------------------------#

Marsaglia_and_Bray() # calling the function to generate 1000 N(0,1) values and store in Z1 and Z2

for i in range (len(a_values)):
    a=a_values[i]
    RHO=2*a/(SIGMA1*SIGMA2) #2a=rho*sigma1*sigma2
    A11,A12,A21,A22=return_A(SIGMA1,SIGMA2,RHO)
    COV_matrix=np.array([[1,2*a],[2*a,4]]) #making this an np array for later use (of transpose, inverse etc..)

    X1=[]
    X2=[]
    #--------------q1.1 done. In X1[], X2[] we have the generated values of X----------#
    for j in range (len(Z1)):
        X1.append(MU[0]+A11*Z1[j])
    for j in range (len(Z2)):
        X2.append(MU[1]+A21*Z1[j]+A22*Z2[j])
    #----------------------------------------------------------------------------------#

    #drawing the histogram corresponding to the different values of a.
    fig = plt.figure(figsize= (35, 50), frameon= True)

    hist, xedges, yedges = np.histogram2d(X1, X2, bins = (15, 15))
    xpos, ypos = np.meshgrid(xedges[:-1]+0.05, yedges[:-1]+0.05 , indexing = 'ij')
    xpos = xpos.ravel()
    ypos = ypos.ravel()
    zpos = 0
    dx=dy=0.4
    dz = hist.ravel()

    #making a 4*1 plot and adding the first subplot at position 1 ---------q1.2 done---------#
    plot_1 = fig.add_subplot(321, projection='3d')
    plot_1.set_title('3D Histogram for Simulated X')
    plot_1.set_xlabel(r'$X_1$')
    plot_1.set_ylabel(r'$X_2$')
    plot_1.set_zlabel('Frequency')
    plot_1.bar3d(xpos, ypos, zpos, dx, dy, dz,  shade = True, zsort = 'max', cmap = 'inferno')

    #plotting the actual density for the above cases
    x1_range=np.linspace(2,10,200) #x1 has a range from 2 to 10 (plot1)
    x2_range=np.linspace(2,20,200) #x2 has a range from 2 to 20 (plot1)

    AX1, AX2 = np.meshgrid(x1_range, x2_range)
    AX = np.empty(AX1.shape + (2,))
    AX[:, :, 0] = AX1
    AX[:, :, 1] = AX2

    Z=[]
    detereminant_E=np.linalg.det(COV_matrix)
    if(detereminant_E==0):
        print('The determinant for COV matrix is 0 and PDF does not exist in case of a=1.0')
    else:
        inverse_E=np.linalg.inv(COV_matrix)
        for r in range(200):
            M=[]
            for s in range(200):
                x=np.array([AX[r,s,0],AX[r,s,1]])
                result=return_multivariate_normal_pdf(x,detereminant_E,inverse_E,np.array(MU))
                M.append(result)
            Z.append(M)
        Z=np.array(Z)
        Z=Z*200*2*(xedges[1]-xedges[0])*(yedges[1]-yedges[0])
        plot_2= fig.add_subplot(322, projection ='3d')
        plot_2.plot_surface(AX1, AX2, Z, cmap ='inferno', label = 'Actual')
        plot_2.set_title('Actual Density surface')
        plot_2.set_xlabel(r'$X_1$')
        plot_2.set_ylabel(r'$X_2$')
        plot_2.set_zlabel('PDF')

        #plotting the actual and generated densities in a common graph
        plot_3= fig.add_subplot(323, projection='3d')
        plot_3.bar3d(xpos, ypos, zpos, dx, dy, dz,  shade = True, zsort = 'max', cmap = 'inferno', alpha=0.3)
        plot_3.plot_surface(AX1, AX2, Z, cmap ='inferno', alpha=0.7)
        plot_3.set_title('Simulated histogram for X vs Actual surface')
        plot_3.set_xlabel(r'$X_1$')
        plot_3.set_ylabel(r'$X_2$')
        plot_3.set_zlabel('Frequency / PDF')

#     plotting for the marginal 1 dimensional cases!
    figpos1=325
    figpos2=326
    if(a==1):
        figpos1=323
        figpos2=324

    # plotting for X1-------------------------------------------------------------------------------
    plot_4 = fig.add_subplot(figpos1)
    counts, bins, _=plot_4.hist(X1, bins = 20, label = 'Simulated',rwidth=0.9)
    xaxis= np.arange(bins[0]-0.5, bins[-1]+0.5, 0.2)
    yaxis= return_univariate_normal_pdf(xaxis, MU[0], SIGMA1**2) * (bins[1] - bins[0]) * len(X1)
    plot_4.plot(xaxis, yaxis, label='Actual')
    plot_4.set_title('X1 marginal distribution with \u03BC = {} and {} = {}'.format(round(np.mean(X1),4), r"$\sigma^{2}$", round(np.std(X1)**2,4)))
    plot_4.set_xlabel('Values')
    plot_4.set_ylabel('Frequency')
    plot_4.legend()

    # plotting for X2-------------------------------------------------------------------------------
    plot_5 = fig.add_subplot(figpos2)
    counts, bins, _ = plot_5.hist(X2, bins = 20, label = 'Simulated',rwidth=0.9)
    xaxis = np.arange(bins[0]-0.5, bins[-1]+0.5, 0.2)
    yaxis = return_univariate_normal_pdf(xaxis, MU[1], SIGMA2**2) * (bins[1] - bins[0]) * len(X2)
    plot_5.plot(xaxis, yaxis, label = 'Actual')
    plot_5.set_title('X2 marginal distribution with \u03BC = {} and {} = {}'.format(round(np.mean(X2),4), r"$\sigma^{2}$", round(np.std(X2)**2),4))
    plot_5.set_xlabel('Values')
    plot_5.set_ylabel('Frequency')
    plot_5.legend()

    mu_array='['+str(np.mean(X1))+','+str(np.mean(X2))+']'
    print("Plots for a = {}".format(a))
    plt.show()
    #we have used a special character \u03BC for showing the greek alpha bet mu

Semester 5/MA 323 (Monte Carlo)/Lab Submissions/Lab 6/180123062_ABSatyaprakashq1.py


# -*- coding: utf-8 -*-
import numpy as np
import math

__all__ = ["haversine",
        	"manhattan",
        	"euclidean",
        	"minkowski",
        	"cosine_similarity",
        	"hamming",
			"mahalanobis"]

def _validate_vector(vector, dtype=None):
    vector = np.asarray(vector, dtype=dtype).squeeze()
    vector = np.atleast_1d(vector)
    if vector.ndim > 1:
        raise ValueError("Input vector should be 1-D.")
    return vector

def _validate_var_type(value, dtype=None):
    if isinstance(value, dtype):
        return value
    else:
        raise ValueError("Input value not of type: " + str(dtype))

def _validate_weights(w, dtype=np.double):
    w = _validate_vector(w, dtype=dtype)
    if np.any(w < 0):
        raise ValueError("Input weights should be all non-negative")
    return w

def hamming(vector1, vector2) :
    if type(vector1) == type(vector2) == int:
        return bin(vector1 ^ vector2).count('1')
    elif type(vector1) == type(vector2) == str:
        if len(vector1) != len(vector2):
            raise ValueError("Undefined for sequences of unequal length.")
        return sum(el1 != el2 for el1, el2 in zip(vector1, vector2))
    else:
        return "Hi"

def haversine(coord1, coord2, R = 6372800):
    '''
    Important to note is that we have to take the radians of the longitude and latitude values.
    R  corresponds to Earths mean radius in meters (6372800)
    '''
    lat1, lon1 = _validate_vector(coord1, dtype=np.double)
    lat2, lon2 = _validate_vector(coord2, dtype=np.double)

    phi1, phi2 = math.radians(lat1), math.radians(lat2)
    dphi       = math.radians(lat2 - lat1)
    dlambda    = math.radians(lon2 - lon1)

    a = math.sin(dphi/2)**2 + \
        math.cos(phi1)*math.cos(phi2)*math.sin(dlambda/2)**2

    return 2*R*math.atan2(math.sqrt(a), math.sqrt(1 - a))

def manhattan(vector_1, vector_2):
    '''
    ## Input
    manhattan([1,2.3213213,3],[4,5.321,6.123])
    ## Output
    -9.1226787
    '''
    vector_1 = _validate_vector(vector_1, dtype=np.double)
    vector_2 = _validate_vector(vector_2, dtype=np.double)
    return minkowski(vector_1, vector_2, p=1)

def euclidean(vector_1, vector_2):
    '''
    ## Input
    euclidean([1,2.3213213,3],[4,5.321,6.123])
    ## Output
    5.267940897849338
    '''
    vector_1 = _validate_vector(vector_1, dtype=np.double)
    vector_2 = _validate_vector(vector_2, dtype=np.double)
    return minkowski(vector_1, vector_2, p=2)

def minkowski(vector_1, vector_2, p=1):
    vector_1 = _validate_vector(vector_1, dtype=np.double)
    vector_2 = _validate_vector(vector_2, dtype=np.double)
    distance = 0.0
    for i in range(len(vector_1)):
            distance += (vector_1[i] - vector_2[i])**p
    return (distance)**(1.0/p)

def cosine_similarity(vector_1, vector_2):
    vector_1 = _validate_vector(vector_1, dtype=np.double)
    vector_2 = _validate_vector(vector_2, dtype=np.double)
    num = np.dot(vector_1, vector_2)
    den = (np.sqrt(np.dot(vector_1, vector_1)) * np.sqrt(np.dot(vector_2, vector_2)))
    return num / den

def mahalanobis(u,v,VI):
    u = _validate_vector(u)
    v = _validate_vector(v)
    VI = np.atleast_2d(VI)
    delta = u - v
    m = np.dot(np.dot(delta, VI), delta)
    return np.sqrt(m)


# import statistics
# from scipy import stats
from collections import Counter

def mean(x):
    # return round(statistics.mean(x), 1)
    # or
    return round(sum(x) / len(x), 1)

def median(x):
    # return round(statistics.median(x), 1)
    # or
    # floor division operator // to get an integer and use it as an index
    index = len(x) // 2
    # Sample with an odd number of observations
    if len(x) % 2:
        return round(sorted(x)[index], 1)
    # Sample with an even number of observations
    return round(sum(sorted(x)[index - 1:index + 1]) / 2, 1)

def mode(x):
    # return int(stats.mode(x)[0])
    # or
    count = Counter(sorted(x))
    # most_common(number of tuples)[list index][tuple index]
    mode_list = [key for key, value in count.items() if value == count.most_common(1)[0][1]]
    return mode_list[0]

def validate(n, x):
    constraints = True
    for number in x:
        if not (number in range(1, 10 ** 5 + 1)):
            constraints = False
            break
    if constraints and 10 <= n <= 2500:
        print(mean(x))
        print(median(x))
        print(mode(x))

def main():
    n = int(input())
    x = list(map(int, input().split()))
    validate(n, x)

if __name__ == "__main__":
    main()


from math import sqrt
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from statsmodels.tsa.stattools import adfuller

def compute_correlation(x,y,r2=False,auto=False):

    '''Take two array-like series to calculate the correlation
    x: numpy.array or pandas.DataFrame: x value for correlation
    y: numpy.array or pandas.DataFrame: y value for correlation

    r2: Boolean (optional): return r-squared value instead of r'''

    '''Need to remove the mean for autocorrelation?'''

    df = pd.DataFrame({'x':x,'y':y})

    if auto:

        df['x'] = df['x'] - df['x'].mean()
        df['y'] = df['y'] - df['y'].mean()

    df.dropna(inplace=True)

    n = len(df)

    df['x2'] = np.square(df['x'])
    df['y2'] = np.square(df['y'])
    df['xy'] = df['x'] * df['y']
    sum_x = df['x'].sum()
    sum_y = df['y'].sum()
    sum_xy = df['xy'].sum()
    sum_x2 = df['x2'].sum()
    sum_y2 = df['y2'].sum()

    corr = (n*(sum_xy) - (sum_x*sum_y)) / (sqrt(((n*(sum_x2) - (sum_x**2)) *((n*(sum_y2) - (sum_y**2))))))

    #corr_test = np.cov(df['x'].values,df['y'].values)[0,1]

    return df, corr

def acf_compute(x,y):

    if isinstance(x,pd.DataFrame) or isinstance(x,pd.Series):

        x = x.dropna().values

    if isinstance(y,pd.DataFrame) or isinstance(y,pd.Series):

        y = y.dropna().values

    nx = len(x)
    ny = len(y)

    x = x[nx-ny:]

    top = np.mean(np.dot((x-np.mean(x)), (y-np.mean(y))))

    bot = np.sum(np.square((x-np.mean(x))))

    acf_r = top/bot

    return acf_r

def autocorrelate(x,shift=1,conf_int=False,lags=None,df=False):

    if isinstance(x,pd.DataFrame) or isinstance(x,pd.Series):

        x = x.values

    n = len(x)

    if lags is None:

        lags = n

    else:

        lags = lags

    r_array = np.empty(lags)
    conf_lower = np.empty(lags)
    conf_upper = np.empty(lags)

    for i in range(lags):

        r_array[i] = acf_compute(x[i:],x[:len(x)-i])
        conf_lower[i] = -1.96 / np.sqrt(len(x)-i)
        conf_upper[i] = 1.96 / np.sqrt(len(x)-i)

    if df:

        r_array = pd.DataFrame(data=r_array)

    if conf_int:

        return r_array, conf_upper, conf_lower

    return r_array

def plot_auto_corr(x,title=None,lags=None):

    auto_corr, conf_upper, conf_lower = autocorrelate(x,conf_int=True,lags=lags)

    plt.plot(auto_corr,linestyle='none',marker='o',color='red')

    for i, x in enumerate(auto_corr):
        plt.vlines(x=i,ymin=min(0,x),ymax=max(0,x))

    plt.fill_between([i for i in range(len(auto_corr))],conf_lower,conf_upper,color='green',alpha=0.2)

    if title is None:
        title = 'Autocorrelation (Lags = {})'.format(len(auto_corr))

    else:

        title = title + ' (Lags = {})'.format(len(auto_corr))
    plt.title(title,fontsize=16)
    plt.show()

def test_stationarity(df, print_results=True, **kwargs):

    '''Use stattools adfuller function with a more DataFrame-friendly format

    df = pandas.DataFrame or pandas.Series: required, used for testing stationarity

    **kwargs = dict, used to feed adfuller arguments'''

    raw_results = adfuller(df,**kwargs)

    df_rows = {fk: fv for fv, fk in zip(raw_results[:4],list(['Test Statistic','P-Value','Lags Used','Observations Taken']))}

    df_rows.update({sk: sv for sk, sv in raw_results[4:-1][0].items()})

    dickey_test_results = pd.DataFrame(index=df_rows.keys(),data=list(df_rows.values()),columns=['Metric'])

    if print_results:
        print('Results of the Augmented Dickey-Fuller Test: \n\n', dickey_test_results.head(10))

    return dickey_test_results


"""
Ajay Kc
013213328
EE 381
Project 1 Part 3

The program checks the probability of getting 4 of a kind card
"""

import numpy as np

def fourOfAKind():

    #drawnCards = np.random.randint(1,53,5)
    drawnCards = np.random.permutation(52)[0:5]
    cardFaces = {}
    for i in drawnCards:
        if (i % 13 in cardFaces):
            cardFaces[i % 13] += 1
        else:
            cardFaces[i % 13] = 1

    for k, v in cardFaces.items():
        if v == 4:
            return 'Success'

    return 'Failure'

successCount = 0
for i in range(0, 100000):
    if fourOfAKind() == 'Success':
        successCount += 1

probability = successCount / 100000
print('The probability of getting a 4-of-a-kind when 5 cards are drawn %s' % (probability))


#Array Mathematics
import numpy

n, m = input().split()
a = [numpy.array(list(map(int,input().split())), int)]
b = [numpy.array(list(map(int,input().split())), int)]

print(numpy.add(a,b))
print(numpy.subtract(a,b))
print(numpy.multiply(a,b))
print(numpy.array(numpy.divide(a,b), int))
print(numpy.mod(a,b))
print(numpy.power(a,b))

#Arrays

def arrays(arr):
    # complete this function
    # use numpy.array
    return numpy.array(arr, float)[::-1]

#Shape and Reshape

import numpy

arr = numpy.array(list(map(int,input().split())))
print(numpy.reshape(arr,(3,3)))

#Transpose and Flatten

import numpy

n, m = input().split()

arr = numpy.array([input().split() for _ in range(int(n))], int)

print(numpy.transpose(arr))
print(arr.flatten())

#Concatenate

import numpy

n, m, p = list(map(int,input().split()))

arr1 = numpy.array([input().split() for _ in range(n)], int)
arr2 = numpy.array([input().split() for _ in range(m)], int)
print(numpy.concatenate((arr1, arr2), axis = 0))

#Zeros and Ones

import numpy

shape = list(map(int,input().split()))

print(numpy.zeros(shape, dtype=int))
print(numpy.ones(shape, dtype=int))

#Eye and Identity

import numpy
numpy.set_printoptions(legacy='1.13')

n, m = list(map(int,input().split()))

print(numpy.eye(n,m))

#Floor, Ceil and Rint

import numpy

numpy.set_printoptions(legacy='1.13')

arr = list(map(float,input().split()))

aux = numpy.floor(arr)
print(aux)
aux = numpy.ceil(arr)
print(aux)
aux = numpy.rint(arr)
print(aux)

#Sum and Prod
import numpy

n,m = list(map(int,input().split()))

arr = []
for _ in range(n):
    arr.append(list(map(int,input().split())))

print(numpy.prod(numpy.sum(arr, axis = 0)))

#Min and Max

import numpy

n, m = list(map(int,input().split()))

arr = []
for _ in range(n):
    arr.append(list(map(int,input().split())))
print(numpy.max(numpy.min(arr, axis=1)))

#Mean, Var, and Std
import numpy
n, m = list(map(int,input().split()))

arr = []
for _ in range(n):
    arr.append(list(map(int,input().split())))

print(numpy.mean(arr, axis=1))
print(numpy.var(arr, axis=0))
print(numpy.around(numpy.std(arr),decimals=11) ) #found numpy.araund in Discussions section

#Dot and Cross

import numpy

n = int(input())

A = []
for _ in range(n):
    A.append(list(map(int, input().split())))

B = []
for _ in range(n):
    B.append(list(map(int, input().split())))

print(numpy.dot(A,B))

#Inner and Outer

import numpy

arr1 = list(map(int,input().split()))
arr2 = list(map(int,input().split()))

print(numpy.inner(arr1, arr2))
print(numpy.outer(arr1, arr2))

#Polynomials
import numpy

arr = list(map(float, input().split()))
n = float(input())

print(numpy.polyval(arr, n))

#Linear Algebra

import numpy

n = int(input())

mat = []
for _ in range(n):
    mat.append(list(map(float,input().split())))
print(numpy.around(numpy.linalg.det(mat), decimals=2))


"""
Part 1 of https://adventofcode.com/2020/day/5

As a sanity check, look through your list of boarding passes.
What is the highest seat ID on a boarding pass?
"""
import numpy as np

def read_data(filename: str) -> list:
    with open(filename, "r") as f:
        data = f.read().split("\n")
    return data

def split_list(li):
    """Split a given list into a right half and left half."""
    half = len(li) // 2
    return li[:half], li[half:]

def get_seat_id(seat: str) -> int:

    """
    Find seat id of a given boarding pass, following the airline's
    'binary space partitioning' rules.
    """

    key = {"F": 0, "B": 1, "L": 0, "R": 1}

    row = list(range(128))
    col = list(range(8))
    for i, char in enumerate(seat):
        if i < 7:
            row = split_list(row)[key[char]]
        else:
            col = split_list(col)[key[char]]

    return row[0] * 8 + col[0]

if __name__ == "__main__":
    seat_ids = []
    for bp in read_data("input.txt"):
        si = get_seat_id(bp)
        seat_ids.append(si)

    print(f"Solution: The highest seat id is {np.max(seat_ids)}")


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
learning and gate with logistic regression

"""
import numpy as np
from tqdm import tqdm, trange

import matplotlib.pyplot as plt

def initizalize_with_zeros(dim):
    w = np.zeros(shape=(dim,1))
    b = 0
    return w, b

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

def cross_entropy_loss_function(m, A, Y):
    c = (-1/m)*np.sum(Y*np.log(A)+(1-Y)*(np.log(1-A)))
    return c

def propagate(w,b,X,Y):
    m = X.shape[1]
    z = (np.dot(w.T, X) + b)

    #compute activation
    A = sigmoid(z)

    #compute cross-entropy-loss
    cost = cross_entropy_loss_function(m, A, Y)

    #backward propagation
    dw = (1/m)*np.dot(X, (A-Y).T)
    db = (1/m)* np.sum(A - Y)
    grads = {"dw" : dw, "db" : db}

    return grads, cost

"""
# Optimization
The goal is to learn ww and bb by minimizing the cost function J.
For a parameter θ, the update rule is θ=θ−α dθ=θ−α dθ,
where α is the learning rate.
"""

def optimize(w, b, X, Y, num_iterations, learning_rate):
    #cost cache
    costs = []

    for i in trange(num_iterations):
        grads, cost = propagate(w, b, X, Y)

        # Retrieve derivatives from grads
        dw = grads["dw"]
        db = grads["db"]

        #update rule
        w = w - (learning_rate * dw)
        b = b - (learning_rate * db)

        if i % 100 == 0:
            costs.append(cost)

    params = {"w":w, "b":b}
    grads = {"dw":dw, "db":db}

    return params, grads, costs

def predict(w, b, X):
    m = X.shape[1]
    Y_prediction = np.zeros((1,m))

    A = sigmoid(np.dot(w.T, X) + b)

    for i in range(A.shape[1]):
        Y_prediction[0, i] = 1 if A[0,i] > 0.5 else 0

    return Y_prediction

if __name__ == '__main__':
    w, b, X, Y = np.random.uniform(size=2), np.random.uniform(size=1), np.array([[0.,1.,0.,1],[0.,0.,1.,1]]), np.array([[0,0,0,1]])
    params, grads, costs = optimize(w, b, X, Y, num_iterations= 10000, learning_rate = 0.01)

    X_test = np.array([np.random.uniform(-1,2,2) for x in range(10)])
    preds = predict(params["w"], params["b"], X_test.T)
    print(preds)

    model_costs = np.squeeze(costs)

    plt.plot(model_costs)
    plt.ylabel('training cost')
    plt.xlabel('iterations (per hundreds)')
    plt.title("Learning rate = 0.01")
    plt.show()


# Problem: https://projecteuler.net/problem=358

from sage.all import *

"""
    . According to https://en.wikipedia.org/wiki/Cyclic_number,
        <quote>
            Conversely, if the digital period of 1/p (where p is prime) is p − 1, then the digits represent a cyclic number.
        </quote> (1)
    and,
        <quote>
            From the relation to unit fractions, it can be shown that cyclic numbers are of the form of the Fermat quotient
                (b^(p-1)-1)/p
            where b is the number base (10 for decimal), and p is a prime that does not divide b. (Primes p that give cyclic numbers in base b are called full reptend primes or long primes in base b).
        </quote> (2)

    . Note that, a prime p is a full reptend prime when
        Mod(10, p).multiplicative_order() is p-1 (which means the cycle length is p-1). (3)

    . Let the cyclic number we want to find be 'alpha'.

    . From (1), we can say that, the cyclic number we want to find is in the form of
        alpha = (1/p) * (10**(p-1))

    . Since the left most digits of the cyclic number is 00000000137, then
        0.00000000137 < 1/p < 0.00000000138
        Therefore, floor(1/0.00000000137) > p > floor(1/0.00000000138)
    -> we have a lowerbound and an upperbound for p. (4)

    . We have that the rightmost digits of alpha is 56789.
      From (2), we have that (10^(p-1)-1)/p = alpha.
                       -> 10^(p-1)          = alpha * p + 1
                       -> 10^(p-1) mod 10^5 = (alpha * p + 1) mod 10^5
                       ->                 0 = {[alpha (mod 10^5)] * [p (mod 10^5)] + 1} (mod 10^5)
                       ->                 0 = [56789 * (p mod 10^5) + 1] (mod 10^5) (5)

    . From (2), (3), (4), (5), we can find the prime that produces alpha using the following algorithm,
        for p in [floor(1/0.00000000138), floor(1/0.00000000137)]:
            if [56789 * (p mod 10^5) + 1] (mod 10^5) == 0 and Mod(10, p).multiplicative_order() == p - 1:
                desired_p = p
                break

    . Note that, due to the definition of cyclic number, each rotation must appear once in the set S = {alpha*k | 1 <= k <= desired_p - 1}
      Therefore, for every position i, the i^th digit of alpha must appear as the last digit in one rotation in S.
      (otherwise, by pigeon hole theorem, there would be two distinct k_1 and k_2 in [1, desired_p - 1] such that alpha * k_1 = alpha * k_2, which disagrees with integer arithmetic).

    . Therefore, we can find the sum of the digits by simply summing up the last digits of desired_p * k for all k in [1, desired_p - 1].
      In other words, digits_sum = sum(k in [1, desired_p-1]) [(desired_p *k) mod 10]
                                 = sum(k in [1, desired_p-1]) [(desired_p mod 10) * (k mod 10)]
                                 = (desired_p mod 10) * sum(k in [1, desired_p-1]) [k mod 10]
      Note that (k mod 10) repeatedly cycle around [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; and 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 = 45
      So sum(k in [1, desired_p-1]) [k mod 10]
       = sum(k in [0, desired_p-1]) [k mod 10]
       = sum([0..9]) * floor((desired_p-1) / 10) + sum([0..(desired_p-1) mod 10])
       = 45 * floor((desired_p-1) / 10) + sum([0..(desired_p-1) mod 10])
      As a result, digits_sum = (desired_p mod 10) * [45 * floor((desired_p-1) / 10) + sum([0..(desired_p-1) mod 10])]
"""

if __name__ == "__main__":
    ans = 0

    p_lowerbound = int(1/0.00000000138)
    p_upperbound = int(1/0.00000000137)

    RIGHT_MOST_DIGITS = 56789
    MOD = 10**5

    p = p_lowerbound
    while p < p_upperbound:
        m = (RIGHT_MOST_DIGITS * (p % MOD) + 1) % MOD
        if m == 0 and (Mod(10, p).multiplicative_order()) == p-1:
            break
        p = next_prime(p)

    digits_sum = 0
    desired_p = p

    sum_0_n = lambda n: n*(n+1)//2

    digits_sum = (desired_p % 10) * (sum_0_n(9) * ((desired_p-1) // 10) + sum_0_n((desired_p-1) % 10))

    ans = digits_sum

    print(ans)


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

def rand(mu, sigma, len):
    return mu + sigma * np.random.randn(len)

def shuffle_in_unison(array_1, array_2, array3=None):
    rng_state = np.random.get_state()
    np.random.shuffle(array_1)
    np.random.set_state(rng_state)
    np.random.shuffle(array_2)
    if array3 is not None:
        np.random.set_state(rng_state)
        np.random.shuffle(array3)

def distance(point):
    return sqrt((point[0][0] - point[1][0])**2 + (point[0][1] - point[1][1])**2)

if __name__ == "__main__":
    print("Header File...")


# Disciplina: Mecânica Quântica (FIS01210)
# Aluno: Ramon Rossa de Paula (00243967)

# "Este trabalho foi produzido em Python, utilizando a IDE Visual Studio Code, exclusivamente por mim. Nenhuma parte deste trabalho (texto e fórmulas) foi copiada digitalmente de outras fontes"

# ____________________________________________________________________________________

# Importações

import math
import numpy as np
from numpy import loadtxt
import matplotlib.pyplot as plt
from scipy import integrate
from numpy import sqrt, exp, log, pi, abs

# ____________________________________________________________________________________

# Calculando a área do resultado da integral fundamental:

def fe(a, ep):
    return sqrt(pi/ep) * exp((-a**2)/(4*ep))

# Código para o gráfico:

a = np.arange(-10, 10, 0.01)

plt.title("Área")
plt.xlabel('α')
plt.ylabel('fe(α)')
plt.grid()

plt.plot(a, fe(a, 0.1))   # Largura proporcional a ε e altura proporcional a 1/ε.
plt.plot(a, fe(a, 0.5))
plt.plot(a, fe(a, 1))
plt.plot(a, fe(a, 1.5))
plt.plot(a, fe(a, 2))
plt.plot(a, fe(a, 5))
plt.plot(a, fe(a, 10))
plt.plot(a, fe(a, 20))
plt.plot(a, fe(a, 50))
plt.plot(a, fe(a, 100))

plt.legend(['ε = 0.1', 'ε = 0.5', 'ε = 1', 'ε = 1.5',
            'ε = 2', 'ε = 5', 'ε = 10',
            'ε = 20', 'ε = 50', 'ε = 100',], loc=1)

plt.show()


# To add a new cell, type '# %%'
# To add a new markdown cell, type '# %% [markdown]'
# %%
#integrantes: GABRIEL GOMEZ, EDUARDO DE LA HOZ, STEPHANIA DE LA HOZ

# %%
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import scipy.linalg as la
import sys
import mpl_toolkits.mplot3d as mpl
from numpy import genfromtxt
from collections import Counter

# %%
def cleaner(df,k):
    return np.array(df[(abs(df[0]-np.mean(df[0])) <= k*np.std(df[0])) & (abs(df[1]-np.mean(df[1])) <= k*np.std(df[1]))])

def gerOutliners(df,k):
    return np.array(df[(abs(df[0]-np.mean(df[0])) > k*np.std(df[0])) | (abs(df[1]-np.mean(df[1])) > k*np.std(df[1]))])
def proy(rData,base):
    u1p=np.dot(rData,base[0])
    u2p=np.dot(rData,base[1])
    u3p=np.dot(rData,base[2])
    u1u1=np.linalg.norm(base[0])
    u2u2=np.linalg.norm(base[1])
    u3u3=np.linalg.norm(base[2])
    u1pdu1=u1p/u1u1
    u2pdu2=u2p/u2u2
    u3pdu3=u3p/u3u3
    sum1=np.zeros((len(rData),3))
    sum2=np.zeros((len(rData),3))
    sum3=np.zeros((len(rData),3))
    for i in range(len(rData)):
        sum1[i]=u1pdu1[i]*base[0,:]
        sum2[i]=u2pdu2[i]*base[1,:]
        sum3[i]=u3pdu3[i]*base[2,:]
    rest=sum1+sum2+sum3
    return rest

# %%
df=pd.read_table('irisdata.txt',skiprows=9,header=None)
df=df.drop(columns=4)
rawdata=np.array(df)
covRawData = np.cov(rawdata.T)
resultRaw = la.eig(covRawData)
rawdata[0,:]

# %%
covRawData

# %%
resultRaw[0].real

# %%
resultRaw[1]

# %%
test=np.array(resultRaw[1])
test[0]

# %%
eugenValue=np.array(resultRaw[0].real)
sumEugen=np.sum(eugenValue)
porEugen=eugenValue/sumEugen
porEugen=porEugen*100

# %%
x=np.arange(4)
fig=plt.figure()
ax=fig.add_axes([0,0,1,1])
lang=['PC1','PC2','PC3','PC4']
ax.bar(lang,porEugen)
plt.show()

# %%
rawtest=df.drop(columns=3)
tt=np.array(test[:,0:3])
t=proy(rawtest,tt)
t

# %%
fig=plt.figure()
ax=fig.add_subplot(111,projection='3d')
ax.scatter3D(t[:,0], t[:,1], t[:,2],c=t[:,2],cmap='Dark2')
plt.show()


import numpy as np
from typing import Callable

import LinEq as eq

def LinearRegression(f, x :np.ndarray):
    y = np.array(list(map(f, x)))
    n = x.shape[0]
    k2 = ( n * x.dot(y) - x.sum() * y.sum()) / ( n * (x**2).sum() - x.sum()**2 )
    k1 = np.average(y) - k2 * np.average(x)
    return lambda x: k1 + k2 * x

def ExponentialRegression(f, x :np.ndarray, l = None):
    y = np.vectorize(f)(x)
    A_l = lambda l: (y.dot(np.exp(l * x)) / np.sum(np.exp(2 * l * x)))
    f_l = lambda l: (x * y).dot(np.exp(l * x)) - A_l(l) * x.dot(np.exp(2 * l * x))

    if l == None:
        print('find root for the returned function and supply it as l')
        return f_l
    else:
        A = A_l(l)
        return lambda x: A * np.exp( l * x )

def PolynomialRegression(f : Callable, x: np.ndarray, order: int) -> np.ndarray:
    y = np.vectorize(f)(x)

    T = []
    for i in range(order * 2 - 1):
        T.append(x**i)
    T = np.array(T)

    A = np.zeros((order, order))
    for i, j in enumerate(T, start= - order + 1):
        diag = np.diag(np.fliplr(A),k=-i)
        diag.setflags(write=True)
        diag.fill(np.sum(j))
    C = T[:order].dot(y).T
    poly = eq.Gaussian_Elimination(A,C[...,None])
    return poly


import sympy as sym
X, h = sym.symbols('X h')
half = sym.Rational(1, 2)
psi = [half*(X-1)*X, 1-X**2, half*(X+1)*X]
dpsi_dX = [sym.diff(psi[r], X) for r in range(len(psi))]

# Element matrix
# (2/h)*dpsi_dX[r]*(2/h)*dpsi_dX[s]*h/2
import numpy as np
d = 2
# Use a numpy matrix with general objects to hold A
A = np.empty((d+1, d+1), dtype=object)
for r in range(d+1):
    for s in range(d+1):
        integrand = dpsi_dX[r]*dpsi_dX[s]*2/h
        A[r,s] = sym.integrate(integrand, (X, -1, 1))
print(A)

# Element vector
# f*psi[r]*h/2, f=1
d = 2
b = np.empty(d+1, dtype=object)
for r in range(d+1):
    integrand = -psi[r]*h/2
    b[r] = sym.integrate(integrand, (X, -1, 1))
print(b)


import sys
sys.path.append('..')
import numpy as np
import matplotlib.pyplot as plt
from chebyspectral import *

deg = 16  # degree of Chebyshev polynomial

# Source term
f = lambda xq: np.exp(4*xq)
fHat = chebfit(f, deg)

# Boundary conditions
bc_value_1 = 0
bc_derivative_order_1 = 1  # Neumann (first derivative)
bc_position_1 = -1
bc_axis_1 = 0
bc_1 = [bc_value_1, bc_derivative_order_1, bc_position_1, bc_axis_1]

bc_value_2 = 0
bc_derivative_order_2 = 0 # Dirichlet
bc_position_2 = 1
bc_axis_2 = 0
bc_2 = [bc_value_2, bc_derivative_order_2, bc_position_2, bc_axis_2]

# Differentiation matrix
l_operator = [0, 0, 1]
L = chebdiff(l_operator, deg)
L, fHat = chebbc(L, fHat, [bc_1, bc_2])

# Compute solution
u = np.dot(np.linalg.pinv(L), fHat)

# Plot solution
N = 100
x = np.linspace(-1, 1, N)
exact_sol = (np.exp(4*x) - 4*np.exp(-4)*(x-1) - np.exp(4))/16
series_sol = chebeval(u, x)

fig, ax = plt.subplots()
ax.plot(x, series_sol , 'b', label='Approximation')
ax.plot(x, exact_sol, 'r--', label='Exact')
handles, labels = ax.get_legend_handles_labels()
ax.legend(handles, labels)
plt.xlabel('x')
plt.ylabel('f(x)')
plt.show()


import numpy as np
def gen_points(num_points):
    r = 0.2828
    all_points = [(r*np.cos(theta), r*np.sin(theta)) for theta in np.linspace(0, 2*np.pi, num_points+1)[:num_points]]
    print(all_points)

gen_points(3)


import numpy as np

from compute_cost import compute_cost
from gradient_descent import gradient_descent
from load_data import load_data
from plot_data import plot_data, plot_cost
from predict import predict

# Linear Regression: Company Profit per City Population

# Load File and Set Initial Parameters

filename = 'city_profit.txt'
x, y = load_data(filename)
size = y.size
theta = np.array([[0.0], [0.0]])
alpha = 0.01
iterations = 1500
population = 175000

# Cost Function

cost = compute_cost(x, y, size, theta=theta)
print(f"With given theta: \n\tCost computed = {cost}\n")

# Gradient Descent

new_theta, cost_history = gradient_descent(x, y, size, theta=theta, alpha=alpha,
                                           iterations=iterations)

# Plot Data and Regression Line

plot_data(x, y, new_theta)

# Plot Cost History

plot_cost(iterations, cost_history)

# Make a Prediction

predict(population, new_theta)


import numpy as np

def L1Loss(x, y):
    return np.mean(np.abs(x - y))

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

def BCELoss(x, y):
    return -(y * np.log(x) + (1 - y) * np.log(1 - x))


import math
import numpy as np
from scipy.special import beta, betaln, comb, gammaln

# Probability mass functions

def beta_binomial_pmf(k, n, a, b, log_scale=False):
    '''
    The pmf of a beta-binomial distribution.

    Parameters
    ----------
    k, integer
        number of "successes".
    n, integer
        number of draws.
    a, positive real
        alpha parameter for the beta-binomial.
    b, positive real
        beta parameter for the beta-binomial.
    log_scale, boolean
        should the pmf be returned on the log scale?

    Returns
    -------
    prob, array-like of positive reals
        probability mass of k
    '''
    if log_scale:
        return (np.log(comb(n, k)) +
                np.log(beta(k + a, n - k + b)) -
                np.log(beta(a, b)))
    else:
        return (comb(n, k) *
                beta(k + a, n - k + b) /
                beta(a, b))

def dirichlet_multinomial_pmf(x, n, a, log_scale=False):
    '''
    The pmf of a Dirichlet-multinomial distribution.

    Parameters
    ----------
    x, array-like of integers
        number of "successes". This can be a list of integers
        if this is just one set of observations, or it can be
        a KxS list of lists or numpy array if there are K
        categories and S samples.
    n, array-like of integers
        number of draws.
    a, array-like of positive reals
        alpha parameters for the Dirichlet multinomial.
        This can be a K-list of alpha values if we have one
        set of observations, or it can be KxS list of lists
        or numpy array if there are K categories and S samples.
    log_scale, boolean
        should the pmf be returned on the log scale?

    Returns
    -------
    prob, array-like of positive reals
        probability mass of k
    '''
    np.seterr(divide='ignore', invalid='ignore')
    x = np.array(x)
    a = np.array(a)
    n = np.array(n)

    # x and a must have the same dimensions.
    assert(np.shape(x) == np.shape(a))

    sum_a = a.sum(axis=0)

    # 1 if the observation was valid (i.e. all x >= 0) and 0 otherwise
    valid_obs = (x >= 0).prod(axis=0)

    if log_scale:
        log_constant = np.log(n) + betaln(sum_a, n)
        # In product in pmf, we want to include only x's that are non-zero.
        summands = np.log(x) + betaln(a, x)
        summands[x == 0] = 0
        # \log (\prod_{k : x_k > 0} x_k B(alpha_k, x_k))
        log_product = summands.sum(axis=0)

        # turn back into np array just in case it was cast to float
        log_pmf = np.array(log_constant - log_product)
        # if the observation was invalid, it has a probability of 0,
        # thus log-prob of -inf
        log_pmf[valid_obs == 0] = -math.inf
        # if there are "no draws" (i.e. everything already observed)
        # then the pmf is 1 iff all of the x's are 0.
        # This is just by convention, since n = 0 is technically
        # an invalid input to the pmf.
        # sum_of_abs_x is 0 iff all x are 0
        sum_of_abs_x = np.abs(x).sum(axis=0)
        log_pmf[n == 0] = np.log(sum_of_abs_x[n == 0] == 0)
        return log_pmf
    else:
        constant = n * beta(sum_a, n)
        # In product in pmf, we want to include only x's that are non-zero.
        multiplicands = x * beta(a, x)
        multiplicands[x == 0] = 1
        # \prod_{k : x_k > 0} x_k B(alpha_k, x_k)
        product = multiplicands.prod(axis=0)

        # turn back into np array just in case it was cast to float
        pmf = np.array(constant / product)
        # if the observation was invalid, it has a probability of 0
        pmf[valid_obs == 0] = 0

        # if there are "no draws" (i.e. everything already observed)
        # then the pmf is 1 iff all of the x's are 0.
        # This is just by convention, since n = 0 is technically
        # an invalid input to the pmf.
        # sum_of_abs_x is 0 iff all x are 0
        sum_of_abs_x = np.abs(x).sum(axis=0)
        pmf[n == 0] = sum_of_abs_x[n == 0] == 0
        # Get an array back from the 1xL matrix where L is the length of x
        return np.squeeze(np.multiply(constant, product))

def mvt_hypergeo_pmf(k, T, log_scale=False):
    '''
    The pmf of a multivariate hypergeometric distribution.

    Parameters
    ----------
    k, array-like of integers
        number of "successes". This can be a list of integers
        if this is just one set of observations, or it can be
        a KxS list of lists or numpy array if there are K
        categories and S samples.
    T, integer
        true number of "successes"
    log_scale, boolean
        should the pmf be returned on the log scale?

    Returns
    -------
    prob, array-like of positive reals
        probability mass of k
    '''
    k = np.array(k)
    T = np.array(T)
    assert(np.shape(k) == np.shape(T))

    # Turn into column vector if only one observation
    k = k[:, None] if np.ndim(k) == 1 else k
    T = T[:, None] if np.ndim(T) == 1 else T

    # Total balls in urn
    N = T.sum(axis=0)
    # Total number of balls sampled from urn
    n = k.sum(axis=0)

    valid_inputs = np.logical_and(k >= 0, T - k >= 0).prod(axis=0)

    if log_scale:
        log_numerator = (gammaln(T + 1) -
                         gammaln(T - k + 1) -
                         gammaln(k + 1)).sum(axis=0)
        log_denominator = gammaln(N + 1) -\
            gammaln(N - n + 1) -\
            gammaln(n + 1)

        log_pmf = log_numerator - log_denominator
        log_pmf[np.logical_not(valid_inputs)] = -math.inf
        return log_pmf
    else:
        numerator = comb(T, k).prod(axis=0)
        denominator = comb(N, n)
        pmf = numerator / denominator
        pmf[np.logical_not(valid_inputs)] = 0
        return pmf

def beta_pdf(x, a, b, log_scale=False):
    x = np.array(x)
    a = np.array(a)
    b = np.array(b)

    if log_scale:
        log_numer = (a - 1) * np.log(x) +\
            (b - 1) * np.log(1 - x)
        log_denom = betaln(a, b)
        return(log_numer - log_denom)
    else:
        numer = np.power(x, a - 1) *\
            np.power(1 - x, b - 1)
        denom = beta(a, b)
        return(numer/denom)

def pval_from_martingale(martingale, running_min=False):
    '''
    Get a p-value from a martingale with initial expectation 1

    Parameters
    ----------
    martingale, array-like
        the martingale
    running_min, boolean
        should the running minimum be taken?

    Returns
    -------
    p, array-like
        p-values
    '''
    pval = np.minimum(1/martingale, 1)
    pval = np.minimum.accumulate(pval) if running_min else pval

    return pval


import numpy as np
import matplotlib.pyplot as plt

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

def gaussian_random_generator(sigma=5, numbers=100000):
    uniform_random_numbers = np.random.rand(numbers, 2)
    rho = sigma * np.sqrt(-2 * np.log(1 - uniform_random_numbers[:, 0]))
    theta = 2 * np.pi * uniform_random_numbers[:, 1]

    gaussian_random = rho * np.array([np.cos(theta), np.sin(theta)])
    gaussian_random_numbers = gaussian_random.flatten()

    min_value = np.min(gaussian_random_numbers)
    max_value = np.max(gaussian_random_numbers)
    x = np.linspace(min_value, max_value + 1, 1000)
    y = gaussian_func(sigma, x)
    plt.hist(gaussian_random_numbers, bins=np.arange(min_value - 0.5, max_value + 1, 1), density=True)
    plt.plot(x, y, linewidth=3)
    plt.xlabel(r'numbers')
    plt.ylabel(r'density')
    plt.savefig("images/q4_" + str(sigma) + "_" + str(numbers) + '.png')
    plt.show()

gaussian_random_generator()


import numpy as np
import pandas as pd

datafile = './data/IBM.csv'

data = pd.read_csv(datafile, sep=',')
# print(data['Adj Close'])

S = data['Adj Close']
N = len(S) - 1
d_t = 1
v_hat = np.log(S[N] / S[0]) / N
print('v_hat (daily return):', v_hat)
print('N * v_hat (annual return):', N * v_hat)
s_2 = 0
for i in range(1, len(S)):
    s_2 += np.power(np.log(S[i] / S[i - 1]) - v_hat, 2)
s_2 /= (N - 1)
print('s (daily volatility):', np.sqrt(s_2))
print('s (annual volatility):', np.sqrt(s_2 * N))

q = 0.5 + 0.5 * (1 / np.sqrt(s_2 / (v_hat ** 2 * d_t) + 1))
q_aprx = 0.5 * 0.5 * v_hat / np.sqrt(s_2) * np.sqrt(d_t)
print('q:', q, 'q approximated:', q_aprx)

U = np.exp(np.sqrt(s_2 * d_t + (v_hat * d_t) ** 2))
D = np.exp(-np.sqrt(s_2 * d_t + (v_hat * d_t) ** 2))
print('U:', U, 'D:', D)

U_aprx = np.exp(np.sqrt(s_2 * d_t))
D_aprx = np.exp(-np.sqrt(s_2 * d_t))
print('U approximated:', U_aprx, 'D approximated:', D_aprx)


import numba
from numba import f8
import numpy as np
from scipy.spatial.qhull import Delaunay
from shapely.geometry import Polygon, Point

@numba.jit(f8(f8[:], f8[:], f8[:]), nopython=True, nogil=True)
def triangle_area(a, b, c):
    return np.abs(a[0] * (b[1] - c[1]) +
                  b[0] * (c[1] - a[1]) +
                  c[0] * (a[1] - b[1])) / 2

@numba.jit(f8[:](f8[:], f8[:], f8[:]), nopython=True, nogil=True)
def random_sample_triangle(a, b, c):
    """
    Uniform sampling of a triangle
    ------------------------------
    Generate uniform random sample from a triangle defined by points A, B
    and C [1]_, [2]_. Point inside the triangle is given

    .. math::
       P = (1 - \sqrt{r_1}) A + (\sqrt{r_1} (1 - r_2))  B + (r_2 \sqrt{r_1}) C,

    where random variables are

    .. math::
       r_1, r_2 \sim \mathcal{U}(0, 1)

    References
    ----------
    .. [1] http://math.stackexchange.com/questions/18686/uniform-random-point-in-triangle
    .. [2] http://mathworld.wolfram.com/TrianglePointPicking.html

    :param a: Vertex of the triangle
    :param b: Vertex of the triangle
    :param c: Vertex of the triangle
    :return: Uniformly distributed random point P.
    """
    # Random variables
    r1 = np.random.random()
    r2 = np.random.random()
    return (1 - np.sqrt(r1)) * a + \
           np.sqrt(r1) * (1 - r2) * b + \
           r2 * np.sqrt(r1) * c

@numba.jit(nopython=True, nogil=True)
def triangle_area_cumsum(mesh):
    """Computes cumulative sum of the areas of the triangle mesh.

    :param mesh: Trianle mesh.
    :return: Cumulative sum the area of the triangle mesh
    """
    area = 0
    rows = mesh.shape[0]
    cumsum = np.zeros(rows)
    for i in range(rows):
        a, b, c = mesh[i, 0, :], mesh[i, 1, :], mesh[i, 2, :]
        area += triangle_area(a, b, c)
        cumsum[i] = area
    return cumsum

class PolygonSample:
    """
    Uniform sampling of convex polygon
    ----------------------------------
    Generates random uniform point from inside of polygon. [1]_

    - Delaunay triangulation to break the polygon into triangular mesh. [2]_
    - Draw random uniform triangle weighted by its area.
    - Draw random uniform sample from inside the triangle.

    .. [1] http://gis.stackexchange.com/questions/6412/generate-points-that-lie-inside-polygon
    .. [2] https://en.wikipedia.org/wiki/Delaunay_triangulation
    """

    def __init__(self, polygon):
        """Polygon to sample.

        :param polygon: Shapely polygon or numpy array of polygon vertices.
        """
        if isinstance(polygon, Polygon):
            self.vertices = np.asarray(polygon.exterior)
        elif isinstance(polygon, np.ndarray):
            self.vertices = polygon
        else:
            raise Exception("")

        # Triangular mesh by Delaunay triangulation algorithm
        self.delaunay = Delaunay(self.vertices)
        self.mesh = self.vertices[self.delaunay.simplices]

        # Cumulative sum of areas of the triangles
        self.weights = triangle_area_cumsum(self.mesh)
        self.weights /= self.weights[-1]  # Normalize values to interval [0, 1]

    def draw(self):
        # Draw random triangle weighted by the area of the triangle and draw
        # random sample
        x = np.random.random()
        i = np.searchsorted(self.weights, x)
        a, b, c = self.mesh[i]
        sample = random_sample_triangle(a, b, c)
        return Point(sample)

import numpy,from scipy,import numba,from numba


#!/usr/bin/python3

from Crypto.Util.number import getPrime
from sympy.ntheory.residue_ntheory import jacobi_symbol
from typing import Tuple
import random

def xgcd(a: int, b: int) -> Tuple[int, int, int]:
    """return (g, x, y) such that a*x + b*y = g = gcd(a, b)"""
    # Extended Euclidean algorithm. Ref: Wikipedia
    x0, x1, y0, y1 = 0, 1, 1, 0
    while a != 0:
        (q, a), b = divmod(b, a), a
        y0, y1 = y1, y0 - q * y1
        x0, x1 = x1, x0 - q * x1
    return b, x0, y0

# Solve modular square root
def solve(factors, x2):
    """
    Solve modular square root
    """
    p = factors[0]
    q = factors[1]
    N = p*q

    # p and q are primes with 3 (mod 4)
    # Ref: https://www.rieselprime.de/ziki/Modular_square_root
    r1 = pow(x2, (p+1)//4, p)
    r2 = pow(x2, (q+1)//4, q)

    g, v2, v1 = xgcd(p, q)

    assert((v2*p + v1*q) % N == 1)
    assert(v1*q % p == 1)
    assert(v2*p % q == 1)

    sol = []
    sol.append((r1*v1*q + r2*v2*p) % N)
    sol.append((r1*v1*q - r2*v2*p) % N)
    sol.append((-r1*v1*q + r2*v2*p) % N)
    sol.append((-r1*v1*q - r2*v2*p) % N)

    # check all 4 solutions
    counter_m1 = 0
    counter_p1 = 0
    for i in sol:
        assert(i*i % N == x2)
        j = jacobi_symbol(i, N)
        if j == -1:
            counter_m1 += 1
        if j == +1:
            counter_p1 += 1

    # Two solutions should have Jacobi symbol +1
    # Other two should have -1
    assert(counter_m1 == 2)
    assert(counter_p1 == 2)

    return sol

def generate_N():
    p = getPrime(80)
    while p % 4 != 3:
        p = getPrime(80)

    q = getPrime(80)
    while q % 4 != 3:
        q = getPrime(80)
    return p*q, (p, q)

N, factors = generate_N()

print(f"N = {N}")

x2 = int(input("x2 ? "))

solutions = solve(factors, x2)

guess = random.choice([-1, 1])
print(f"j_guess = {guess}")

x = int(input("x ? "))

if (x*x) % N == x2:
    J = jacobi_symbol(x, N)
    print("Outcome = Heads" if guess == J else "Outcome = Tails")
else:
    print("Time to call The Judge.")


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

data = pd.read_csv('file/Salary_Data.csv')
list1=list(data['YearsExperience'])
list2 = list(data['Salary'])
n = len(list1)

sx = 0
sx2 = 0
sx3 = 0
sx4 = 0
sy = 0
sxy = 0
sx2y = 0
for i in range(n):
    sx = sx + list1[i]
    sx2 = sx2 + (list1[i])**2
    sy = sy + list2[i]
    sxy = sxy + list1[i]*list2[i]
    sx3 = sx3 + (list1[i])**3
    sx4 = sx4 + (list1[i])**4
    sx2y = sx2y + ((list1[i])**2)*list2[i]

A = np.array([[n,sx],[sx,sx2]])
B = np.array([sy,sxy])
A2 = np.array([[n,sx,sx2],[sx,sx2,sx3],[sx3,sx3,sx4]])
B2 = np.array([sy,sxy,sx2y])
X = np.dot(np.linalg.inv(A),B)
X2 = np.dot(np.linalg.inv(A2),B2)

# degree 1 and 2
def LR(x):
    y = X[1]*x + X[0]
    return y
def QR(m):
    n = X2[2]*m*m + X2[1]*m + X2[0]
    return n

list3 = []
list4 = []
for j in list1:
    list3.append(LR(j))
    list4.append(QR(j))

# calculating mean squared  error
ssr = 0
sse = 0
sst = 0
er = 0
er2 = 0
ssr2 = 0
sse2 = 0
sst2 = 0
avg = sum(list2)/n
for k in range(n):
    ssr = ssr + (list3[k] - avg)**2
    sse = sse + (list2[k] - list3[k])**2
    sst = sst + (list2[k] - avg)**2
    er = er + (list2[k] - list3[k])**2
    er2 = er2 + (list2[k] - list4[k])**2

    ssr2 = ssr2 + (list4[k] - avg)**2
    sse2 = sse2 + (list2[k] - list4[k])**2
    sst2 = sst2 + (list2[k] - avg)**2

print("\nR**2 for linear is : %f "%(ssr/sst))
print("R**2 for Quadratic : %f "%(ssr2/(sse2+ssr2)))
print("So better is Linear Interpolation.")
print("Function is y = %f *x + %f "%(X[1],X[0]))
print("x - Year of experinece & y - salary.\n")

# plotting the curves
plt.scatter(list1,list2, marker='o',s=90,c='m')
plt.plot(list1,list3,'y',linewidth=8,label='Degree 1')
plt.plot(list1,list4,'c',linewidth=4,label='Degree 2')
plt.xlabel("Years of Experience")
plt.ylabel("Salary")

plt.legend()
plt.show()

# uncomment this to run model on input data

#case = float(input("Enter x : "))
#print("y is : %f"%LR(case))