import numpy as np

def CalcVonMiesesEquivalentStress(sigma_A, sigma_B ):
    """
    Calculate the von Mises Equivalent stress for a planar (2D) situations
    using the principal stresses sigma_A and sigma_B, with sigma_A > sigma_B
    :param sigma_A:  the first principal stress
    :param sigma_B:  the second principal stress:
    :return: the von Mises equivalent stress
    """
    sigma_eq = sigma_A**2 - sigma_A * sigma_B + sigma_B**2
    sigma_eq = np.sqrt(sigma_eq)
    return sigma_eq

def CalcVonMiesesFoS(sigma_A, sigma_B, Sy):
    vonMisesEq = CalcVonMiesesEquivalentStress(sigma_A, sigma_B)
    if vonMisesEq == 0.0:
        vonMisesEq = 0.00000001
    FoS_vonMisesEq = Sy / vonMisesEq

    return [ vonMisesEq, FoS_vonMisesEq ]

def CalcTrescaEquicalentStress(sigma_A, sigma_B ):
    """
    \
    :param sigma_A:
    :param sigma_B:
    :return:
    """
    s1 = sigma_A
    s2 = sigma_B
    if sigma_B > sigma_A:
        s2 = sigma_A
        s1 = sigma_B

    stress = (s1 - s2)/2

    return stress

def CalcTrescaFoS(sigma_A, sigma_B, Sy ):

    s1 = sigma_A
    s2 = sigma_B
    if sigma_B > sigma_A:
        s2 = sigma_A
        s1 = sigma_B

    stress = CalcTrescaEquicalentStress(s1, s2)

    if stress == 0.0:
        stress = 0.00000001

    if s1 == 0.0:
        s1 = 0.00000001

    if s2 == 0.0:
        s2 = 0.00000001

    #FoS_TrescaEqStress = 0
    if s1 >= s2 and s1 >= 0 and s2 >= 0:
        FoS_TrescaEqStress = Sy / s1
    elif s1 >= 0 and s2 < 0:
        FoS_TrescaEqStress = Sy / 2 / stress
    elif s1 < 0 and s2  < s1:
        FoS_TrescaEqStress = -Sy / s2

    #FoS_TrescaEqStress = Sy/(stress)

    return [stress, FoS_TrescaEqStress]

def CalcPrincipalStressFos(sigma_A, sigma_B, Sy ):
    if sigma_A == 0.0:
        sigma_A = 0.00000001

    if sigma_B == 0.0:
        sigma_B = 0.00000001

    n1 = Sy / sigma_A
    n2 = Sy / sigma_B

    return min(n1,n2)

def CalcMNSTStressFoS(s1, s3, Sut, Suc):

    if s1 < 0.000001 and s1 > -0.000001:
        s1 = 0.0001

    if s3 < 0.000001 and s3 > -0.000001:
        s3 = 0.0001

    case = 0
    stress = 0
    n = 0
    if s1 >= 0 and s3 >= 0 and s1 >= s3:
        case = 1
        n = Sut / s1
        stress = s1
    elif s1 >= 0 and s3 >= 0 and s3 > s1:
        case = 2
        n = Sut / s3
        stress = s3
    elif s1 < 0 and s3 >= 0 and -Sut / Suc > s3 / s1:
        case = 3
        n = Sut / s3
        stress = s3
    elif s1 < 0 and s3 >= 0 and -Sut/Suc <= s3/s1:
        case = 4
        n = Suc / s1
        stress = s1
    elif s1 < 0 and s3 < 0 and -Suc/-Suc >= s3/s1:
        case = 5
        n = Suc / s1
        stress = s1
    elif s1 < 0 and s3 < 0 and -Suc/-Suc < s3/s1:
        case = 6
        n = Suc / s3
        stress = s3
    elif s1 >= 0 and s3 < 0 and -Suc / Sut > s3 / s1:
        case = 7
        n = Suc / s3
        stress = s3
    elif s1 >= 0 and s3 < 0 and -Suc / Sut < s3 / s1:
        case = 8
        n = Sut / s1
        stress = s1

   # print( -Suc / Sut, "  ",  s3 / s1, " ", case)

    return [stress, abs(round(n,2))]

def CalcMMStressFoS(s1, s3, Sut, Suc):

    # swap s1 and s3 so that s1 > s3
    if s1 < s3:
        t = s1
        s1 = s3
        s3  = t

    if s1 < 0.000001 and s1 > -0.000001:
        s1 = 0.0001

    if s3 < 0.000001 and s3 > -0.000001:
        s3 = 0.0001

    case  = 0
    s = 0
    FoS = 0
    if s1 >= s3 and s3 >= 0:
        FoS = Sut / s1
        s = s1
        case = 1
    elif s1 >= 0 and s3 < 0 and abs(s3/s1) <= 1.0:
        FoS = Sut / s1
        s = s1
        case = 2
    elif  s1 >= 0 and s3 < 0 and abs(s3/s1) > 1.0:
        n = ((Suc - Sut) * s1)/(Suc* Sut) - s3/Suc
        FoS = 1/n
        s = np.sqrt(s1**2 + s3**2)
        case = 3
    elif s1 <=0 and s3 < s1:
        FoS = -Suc/s3
        s = s3
        case = 4

    return [s, abs(round(FoS, 2))]

def CalcBCMStressFoS(s1, s3, Sut, Suc):
    # swap s1 and s3 so that s1 > s3
    if s1 < s3:
        t = s1
        s1 = s3
        s3 = t

    if s1 < 0.000001 and s1 > -0.000001:
        s1 = 0.0001

    if s3 < 0.000001 and s3 > -0.000001:
        s3 = 0.0001

    case = 0
    s = 0
    FoS = 0

    if s1 >= s3 and s3 >= 0:
        FoS = Sut/s1
        s = s1
    elif  s1 >= 0 and s3 <= 0:
        n = s1/Sut - s3/Suc
        FoS = 1/n
        s = np.sqrt(s1**2 + s3**2)
    elif s1 <= 0 and s3 <= 0:
        FoS = -Suc /s3
        s = s3

    return [s, abs(round(FoS, 2))]


# -*- coding: utf-8 -*-
# <nbformat>3.0</nbformat>

# <markdowncell>

# # Linear Regression with Gradient Descent Algorithm
#
# This notebook demonstrates the implementation of linear regression with gradient descent algorithm.
#
# Consider the following implementation of the gradient descent loop with NumPy arrays based upon [1]:

# <codecell>

def gradient_descent_numpy(X, Y, theta, alpha, num_iters):
    m = Y.shape[0]

    theta_x = 0.0
    theta_y = 0.0

    for i in range(num_iters):
        predict = theta_x + theta_y * X
        err_x = (predict - Y)
        err_y = (predict - Y) * X
        theta_x = theta_x - alpha * (1.0 / m) * err_x.sum()
        theta_y = theta_y - alpha * (1.0 / m) * err_y.sum()

    theta[0] = theta_x
    theta[1] = theta_y

# <markdowncell>

# To speedup this implementation with Numba, we need to add the `@jit` decorator to annotate the function signature.  Then, we need to expand the NumPy array expressions into a loop.  The resulting code is shown below:

# <codecell>

from numba import autojit, jit, f8, int32, void

@jit(void(f8[:], f8[:], f8[:], f8, int32))
def gradient_descent_numba(X, Y, theta, alpha, num_iters):
    m = Y.shape[0]

    theta_x = 0.0
    theta_y = 0.0

    for i in range(num_iters):
        err_acc_x = 0.0
        err_acc_y = 0.0
        for j in range(X.shape[0]):
            predict = theta_x + theta_y * X[j]
            err_acc_x += predict - Y[j]
            err_acc_y += (predict - Y[j]) * X[j]
        theta_x = theta_x - alpha * (1.0 / m) * err_acc_x
        theta_y = theta_y - alpha * (1.0 / m) * err_acc_y

    theta[0] = theta_x
    theta[1] = theta_y

# <markdowncell>

# The rest of the code generates some artificial data to test our linear regression algorithm.

# <codecell>

import numpy as np
import pylab
from timeit import default_timer as timer

def populate_data(N):
    noise = np.random.random(N).astype(np.float64)
    X = np.arange(N, dtype=np.float64)
    slope = 3
    Y = noise * (slope * X)
    return X, Y

def run(gradient_descent, X, Y, iterations=1000, alpha=1e-6):
    theta = np.empty(2, dtype=X.dtype)

    ts = timer()
    gradient_descent(X, Y, theta, alpha, iterations)
    te = timer()

    timing = te - ts

    print "x-offset = {}    slope = {}".format(*theta)
    print "time elapsed: {} s".format(timing)

    return theta, timing

def plot(X, theta, c='r'):
    result = theta[0] + theta[1] * X
    pylab.plot(X, result, c=c, linewidth=2)

# <markdowncell>

# We will a benchmark with 50 elements to compare the pure python version against the numba version.

# <codecell>

N = 50
X, Y = populate_data(N)
pylab.scatter(X, Y, marker='o', c='b')
pylab.title('Linear Regression')

print 'Python'.center(30, '-')
theta_python, time_python = run(gradient_descent_numpy, X, Y)

print 'Numba'.center(30, '-')
theta_numba, time_numba  = run(gradient_descent_numba, X, Y)

# make sure all method yields the same result
assert np.allclose(theta_python, theta_numba)

print 'Summary'.center(30, '=')
print 'Numba speedup %.1fx' % (time_python / time_numba)

plot(X, theta_numba, c='r')
pylab.show()

# <markdowncell>

#
# ## References
#
# [1] http://aimotion.blogspot.com/2011/10/machine-learning-with-python-linear.html


import numpy as np

def conv_nested(image, kernel):
    """A naive implementation of convolution filter.

    This is a naive implementation of convolution using 4 nested for-loops.
    This function computes convolution of an image with a kernel and outputs
    the result that has the same shape as the input image.

    Args:
        image: numpy array of shape (Hi, Wi)
        kernel: numpy array of shape (Hk, Wk)

    Returns:
        out: numpy array of shape (Hi, Wi)
    """
    Hi, Wi = image.shape
    Hk, Wk = kernel.shape
    out = np.zeros((Hi, Wi))

    # YOUR CODE HERE
    for i in range(Hi - 1):
        for j in range(Wi - 1):
            for m in range(Hk):
                for n in range(Wk):
                    out[i, j] = out[i, j] + \
                        image[i - m + 1, j - n + 1] * kernel[m, n]
    # END YOUR CODE

    return out

def zero_pad(image, pad_height, pad_width):
    """ Zero-pad an image.

    Ex: a 1x1 image [[1]] with pad_height = 1, pad_width = 2 becomes:

        [[0, 0, 0, 0, 0],
         [0, 0, 1, 0, 0],
         [0, 0, 0, 0, 0]]         of shape (3, 5)

    Args:
        image: numpy array of shape (H, W)
        pad_width: width of the zero padding (left and right padding)
        pad_height: height of the zero padding (bottom and top padding)

    Returns:
        out: numpy array of shape (H+2*pad_height, W+2*pad_width)
    """

    H, W = image.shape
    #out = None

    # YOUR CODE HERE
    out = np.zeros((pad_height * 2 + H, pad_width * 2 + W))
    for i in range(H):
        for j in range(W):
            out[i + pad_height, j + pad_width] = image[i, j]
    # END YOUR CODE
    return out

def conv_fast(image, kernel):
    """ An efficient implementation of convolution filter.

    This function uses element-wise multiplication and np.sum()
    to efficiently compute weighted sum of neighborhood at each
    pixel.

    Hints:
        - Use the zero_pad function you implemented above
        - There should be two nested for-loops
        - You may find np.flip() and np.sum() useful

    Args:
        image: numpy array of shape (Hi, Wi)
        kernel: numpy array of shape (Hk, Wk)

    Returns:
        out: numpy array of shape (Hi, Wi)
    """
    Hi, Wi = image.shape
    Hk, Wk = kernel.shape
    out = np.zeros((Hi, Wi))

    # YOUR CODE HERE
    image = zero_pad(image, Hk, Wk)
    kernel = np.flip(np.flip(kernel, 1), 0)
    for i in range(Hi):
        for j in range(Wi):
            out[i, j] = sum(
                sum(kernel * image[i + 2:i + 2 + Hk, j + 2:j + 2 + Wk]))
    # END YOUR CODE

    return out

def conv_faster(image, kernel):
    """
    Args:
        image: numpy array of shape (Hi, Wi)
        kernel: numpy array of shape (Hk, Wk)

    Returns:
        out: numpy array of shape (Hi, Wi)
    """
    Hi, Wi = image.shape
    Hk, Wk = kernel.shape
    out = np.zeros((Hi, Wi))

    # YOUR CODE HERE
    pass
    # END YOUR CODE

    return out

def cross_correlation(f, g):
    """ Cross-correlation of f and g

    Hint: use the conv_fast function defined above.

    Args:
        f: numpy array of shape (Hf, Wf)
        g: numpy array of shape (Hg, Wg)

    Returns:
        out: numpy array of shape (Hf, Wf)
    """

    out = None
    # YOUR CODE HERE
    g = np.flip(np.flip(g, 0), 1)
    out = conv_fast(f, g)

    # END YOUR CODE

    return out

def zero_mean_cross_correlation(f, g):
    """ Zero-mean cross-correlation of f and g

    Subtract the mean of g from g so that its mean becomes zero

    Args:
        f: numpy array of shape (Hf, Wf)
        g: numpy array of shape (Hg, Wg)

    Returns:
        out: numpy array of shape (Hf, Wf)
    """
    # YOUR CODE HERE
    tot = sum(sum(g))
    ave = tot / (g.shape[0] * g.shape[1])
    g = g - ave
    out = cross_correlation(f, g)
    # END YOUR CODE

    return out

def normalized_cross_correlation(f, g):
    """ Normalized cross-correlation of f and g

    Normalize the subimage of f and the template g at each step
    before computing the weighted sum of the two.

    Args:
        f: numpy array of shape (Hf, Wf)
        g: numpy array of shape (Hg, Wg)

    Returns:
        out: numpy array of shape (Hf, Wf)
    """

    # YOUR CODE HERE
#    print(np.shape(f));
#    print(np.shape(g));

#    sumf=sum(sum(f));
#    avef=sumf/(f.shape[0]*f.shape[1]);
#    sigf=sum(sum(np.abs(f-avef)))/(f.shape[0]*f.shape[1]);
#    nomf=(f-avef)/sigf;
    Hi, Wi = f.shape
    Hk, Wk = g.shape

    aveg = sum(sum(g))/ (Hk*Wk)
    sigg = sum(sum(np.abs(g - aveg))) / (Hk*Wk)
    kernel = (g - aveg) / sigg

    out = np.zeros((Hi, Wi))
    image = zero_pad(f, Hk, Wk)
    for i in range(Hi):
        for j in range(Wi):
            avef = sum(
                sum(image[i + 2:i + 2 + Hk, j + 2:j + 2 + Wk])) / (Hk * Wk)
            sigf = sum(
                sum(np.abs(image[i + 2:i + 2 + Hk, j + 2:j + 2 + Wk] - avef))) / (Hk * Wk)
            out[i, j] = sum(
                sum(kernel * (image[i + 2:i + 2 + Hk, j + 2:j + 2 + Wk] - avef) / sigf))

    # END YOUR CODE

    return out


import numpy as np

from typing import Tuple

from icecream import ic

ic.configureOutput(prefix="", outputFunction=print)

def bin_data(np_array_in: np.ndarray, nbr_bins: int) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
    """Get bins for binning the data, large enough that no edge effect issues - will always be possible
    to find right bin using np.searchsorted on the output bin edges.

    Arguments:
        np_array_in: the data to bin
        nbr_bins: the nbr of bins to use

    Returns:
        bin_limits: the limits of the bins; will be nbr_bins+1 long
        bin_mids: the middle of the bins; will be nbr_bins long
        array_bin_indexes: which bin each of the entries in np_array_in should got to; will be same
            length as np_array_in

    example of use:

    ```
    nbr_bins = 20

    bin_limits, bin_mids, array_bin_indexes = get_bins(some_array, nbr_bins)

    dict_entries_in_their_bin = {}
    for crrt_bin in range(nbr_bins):
        dict_entries_in_their_bin[crrt_bin] = []

    for crrt_bin_index, crrt_entry in enumerate(array_bin_indexes, some_array):
        dict_entries_in_their_bin[crrt_bin_index].append(crrt_entry)
    ```

    NOTES:
        could possibly be (partly) rewritten with np.digitize
        we already use np.searchsorted for speed
    """

    assert len(np_array_in.shape) == 1, "only implemented for input arrays of size 1"
    assert nbr_bins > 0, "need a positive number of bins"

    val_min = np.min(np_array_in)
    val_max = np.max(np_array_in)

    # need a bit wider bins
    if val_min == 0:
        val_min = -val_max * 0.001
    elif val_min >= 0:
        val_min = val_min * 0.99
    else:
        val_min = val_min * 1.01

    if val_max == 0:
        val_max = -val_min * 0.001
    elif val_max >= 0:
        val_max = val_max * 1.01
    else:
        val_max = val_max * 0.99

    bin_width = (val_max - val_min) / nbr_bins
    bin_limits = np.arange(val_min, val_max+bin_width/2.0, bin_width)
    bin_mids = (bin_limits[:-1] + bin_limits[1:]) / 2.0

    array_bin_indexes = np.searchsorted(bin_limits, np_array_in, side="left")

    return (bin_limits, bin_mids, array_bin_indexes)

array_test = np.array([34.5, 2.0, 23.3, 9.5, 11, 12, 14, 13, 13.9, 27.3])
nbr_bins = 4
bin_limits, bin_mids, array_bin_indexes = bin_data(array_test, nbr_bins)

ic(array_test)
ic(nbr_bins)
ic(bin_limits)
ic(bin_mids)
ic(array_bin_indexes)


'''
N_sim: number of simulations
T: horizon
dt: step length in years
sigma: volatility per year
mu: drift terms (moving average or long-term mean for stock returns)
S0: initial stock price
'''

from numpy.random import standard_normal
from numpy import array, zeros, sqrt, shape
from pylab import *

S0 = 10.222

T =1
dt =0.0002
sigma = 0.4
mu = 1
N_Sim = 10

Steps=round(T/dt); #Steps in years
S = zeros([N_Sim, Steps], dtype=float)
x = range(0, int(Steps), 1)

for j in range(0, N_Sim, 1):
        S[j,0]= S0
        for i in x[:-1]:
                S[j,i+1]=S[j,i]+S[j,i]*(mu-0.5*pow(sigma,2))*dt+sigma*S[j,i]*sqrt(dt)*standard_normal();
        plot(x, S[j])

title('Simulations %d Steps %d Sigma %.6f Mu %.6f S0 %.6f' % (int(N_Sim), int(Steps), sigma, mu, S0))
xlabel('steps')
ylabel('stock price')
show()


# Find the minimum value of the average cost for the given cost function on the given intervals.
# C(x) = x**3 + 29*x + 432

from sympy import solve, lambdify, symbols, diff, pprint, pretty
import matplotlib.pyplot as plt
import numpy as np

x = symbols('x', positive = True ) # 0 <= x
C = x**3 + 29*x + 432
avgC = C / x

domain_end = 20

g_xlim = [ 10, 20 ]
g_ylim = [-5, 70]

lam_x = lambdify( x, avgC, np )

x_vals = np.linspace( g_xlim[0], g_xlim[1], 1000, endpoint=True )
y_vals = lam_x( x_vals )

plt.plot( x_vals, y_vals, label = '' )

# The minimum value of the average cost over the interval 1 <= x <=10

daC = diff( avgC, x, 1 )

min = solve( daC, x )[ 0 ]

# Global Min
avgC.subs( { x: min } )

# Plotted Area Min
y_vals.min()

plt.show()


import theano
import theano.tensor as T
import numpy as np

# create artificial training data
x_train = np.linspace(-1, 1, 101)
t_train = 2 * x_train + np.random.randn(*x_train.shape) * 0.33

# define symbolic Theano variables
x = T.scalar()
t = T.scalar()

# define model: linear regression
# no bias term
def model(x, w):
    return x * w

w = theano.shared(0.0)
y = model(x, w)

cost = T.mean((t - y) ** 2)
g = T.grad(cost, w)
updates = [(w, w - g * 0.01)]

# compile theano function
train = theano.function([x, t], cost, updates=updates,allow_input_downcast=True)

# train model
for ii in range(20):
    print "iteration {}".format(ii + 1)
    for x, t in zip(x_train, t_train):
        train(x, t)
    print "w = {}".format(w.get_value()) + '\n'


''' NOTE: The Pagerank Algorithm is essentially not a part of our defination. It has been used to illustrate the fact steady state is actually,
# what we intended to find through Page Rank Algorithm as well. The page rank algorithm has been imported from Wikepedia.'''

import numpy as np

def pagerank(M, num_iterations: int = 4500, d: float = 0.85):
    """PageRank: The trillion dollar algorithm."""
    N = M.shape[1]
    v = np.random.rand(N, 1)
    v = v / np.linalg.norm(v, 1)
    M_hat = (d * M + (1 - d) / N)
    for i in range(num_iterations):
        v = M_hat @ v
    return v

n = int(input("Enter the number of rows:"))
m = int(input("Enter the number of columns:"))
print("Enter the entries rowise (separated by space): ")
matrix=[]
for i in range(n):
    a=[]
    for j in range(m):
        a.append(float(input()))
    matrix.append(a)

M=np.array(matrix)

# v = pagerank(M, 100, 0.86)
v_absolute=pagerank(M, 100, 1)
print("Pagerank of given Network: ")
print(v_absolute)
# print("Real time Value: ")
# print(v)


#!/usr/bin/env python

if __name__ == '__main__':

    from argparse import ArgumentParser
    from math import exp, sqrt, sin, cos, atan2, pi
    import numpy as np

    min_val = -1.0
    max_val = 1.0
    default_points = 10
    arg_parser = ArgumentParser(description='produce a 3D vector field')
    arg_parser.add_argument('-x', type=int, default=default_points,
                            help='number of x points')
    arg_parser.add_argument('-y', type=int, default=default_points,
                            help='number of y points')
    arg_parser.add_argument('-z', type=int, default=default_points,
                            help='number of z points')
    options = arg_parser.parse_args()
    fmt_str = '{x:.4f},{y:.4f},{z:.4f},{v_x:.8f},{v_y:.8f},{v_z:.8f}'
    print 'x,y,z,v_x,v_y,v_z'
    for z in np.linspace(0.0, max_val, num=options.z, endpoint=True):
        for x in np.linspace(min_val, max_val, num=options.x, endpoint=True):
            for y in np.linspace(min_val, max_val, num=options.y, endpoint=True):
                d = sqrt(x**2 + y**2 + z**2)
                v = (1.0 - exp(-d))*exp(-d)
                theta = atan2(y, x)
                v_x = v*sin(-theta)
                v_y = v*cos(theta)
                v_z = 0.1*exp(-3.0*z)
                print fmt_str.format(x=x, y=y, z=z,
                                     v_x=v_x, v_y=v_y,v_z=v_z)


import numpy as np
import matplotlib.pyplot as plt
from ancillary import plot
from sklearn.metrics import accuracy_score

"""
File: perceptron.py
Author: Rafal Marguzewicz
Email:  rafal.marguzewicz@altimi.com
Github: https://github.com/pceuropa/
Description: Perceptron Rule
"""

class Perceptron(object):

    def __init__(self, eta: float = 0.01, epochs: int = 50):
        self.eta = eta  # learning reate
        self.epochs = epochs

    def train(self, X: np.ndarray, target: np.ndarray):  # Perceptron Rule
        self.w = np.zeros(1 + X.shape[1])
        self.err = []

        print('Training progress..')
        for epoch in range(self.epochs):
            errors = 0
            for x, y in zip(X, target):
                update = self.eta * (y - self.predict(x))
                self.w[1:] += update * x
                self.w[0] += update
                errors += int(update != 0.0)

            accuracy = int(accuracy_score(self.predict(X), target) * 100)
            self.err.append(accuracy)
            plot(X, target, self, epoch, accuracy, self.w)
        return self

    def dot_product(self, X: np.ndarray) -> np.float64:
        return np.dot(X, self.w[1:]) + self.w[0]

    def predict(self, X: np.ndarray) -> int:
        return np.where(self.dot_product(X) >= 0.0, 1, 0)


# Linear Regression
#%%
import numpy as np
import random
from matplotlib import pyplot as plt

#%%
class LinearRegression():
    def __init__(self):
        self.w = random.random()
        self.b = random.random()

    def train(self, X, y, print_params = False):
        """ X is M x 1 matrix and y is M x 1 matrix """
        alpha = 0.001
        thresh = 1.1
        i = 1
        m = y.shape[0]
        while(True):
            y_pred = self.w * X + self.b
            J_train = np.sum((y_pred - y)**2) / m
            dw = 2 * np.sum((y_pred - y) * X) / m
            db = 2 * np.sum(y_pred - y) / m
            self.w = self.w - alpha * dw
            self.b = self.b - alpha * db
            if print_params:
                print("Step #{0}".format(i))
                print("J_train:", J_train)
                print("w:", self.w, "b:", self.b)
                print()
            i += 1
            if J_train < thresh:
                print("=> Training is complete.")
                break

    def predict(self, x_test):
        """ Returns the prediction for all x_test """
        return self.w * x_test + self.b
#%%
# Generating random dataset
# Let's assume we have a straight line: y = 4 * x + 10,
# We need to create a dataset that approcimately represents this line.
x = np.random.randn(1000, 1) + 4
rand_bias = np.random.randn(1000, 1)
y = 4 * x + 10 + rand_bias
print("x is", x.shape)
print("y is", y.shape)

#%%
# Splitting dataset into training and test sets
x_train = x[:800,:]
y_train = y[:800,:]
x_test = x[800:,:]
y_test = y[800:,:]
print("x_train:", x_train.shape)
print("y_train:", y_train.shape)
print("x_test:", x_test.shape)
print("y_test:", y_test.shape)
#%%
# Plot test set examples
# plt.figure(1)
# plt.plot(x_test, y_test, "r*")
# plt.show()
#%%
# Create and traing a linear regression model
model = LinearRegression()
model.train(x_train, y_train)

#%%
# Generating predictions for test set
y_pred = model.predict(x_test)
J_test = np.sum((y_pred - y_test)**2) / y_pred.shape[0]
print("J_test:", J_test)

#%%
# Plotting the model against the data examples
xline = np.array([[np.min(x_train)], [np.max(x_train)]])
yline = model.predict(xline)
plt.figure(0)

plt.plot(x, y, "r*")
plt.plot(xline, yline)
plt.show()


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

Find the sum of all the primes below two million.
'''

import numpy as np
from math import isqrt

def primesum(a: int):

    arr = np.arange(a, dtype = int)
    zero = np.zeros(a)

    arr = np.where(arr%2 == 0, zero, arr)
    arr = np.where(arr%3 == 0, zero, arr)
    arr = np.where(arr%5 == 0, zero, arr)
    arr = np.where(arr%7 == 0, zero, arr)

    i = 7
    while i < (isqrt(len(arr))+1):
        if arr[i] != 0:
            if arr[i]%i == 0:
                arr = np.where(arr%i == 0, zero, arr)
                arr[i] = i
        i += 1

    arr = np.insert(arr, 0, [2, 3, 5, 7])
    arr = arr.sum() - 1

    return arr

def main():
    a = 2000000
    print('number of primes less than a: ', primesum(a))

if __name__=='__main__':
    main()


from scipy.sparse import csr_matrix
from scipy.sparse.linalg import svds
import numpy as np # linear algebra
import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)

'''Collaborative Filtering model'''

class CFRecommender:

    MODEL_NAME = 'Collaborative Filtering'

    def __init__(self, recommendation_sytem, items_df=None):
        #print("Welcome to collaborative filtering recommender")
        self.cf_predictions_df = self.collaborativeFR_config(recommendation_sytem.get_interactions_train_df())
        self.items_df = items_df

    def get_model_name(self):
        return self.MODEL_NAME

    def collaborativeFR_config(self, interactions_train_df):
         # Creating a sparse pivot table with users in rows and items in columns

        #users_items_pivot_matrix_df = interactions_train_df.pivot(index='personId', columns='postId', values='eventStrength').fillna(0)
        users_items_pivot_matrix_df = pd.pivot_table(interactions_train_df, index='personId', columns='postId').fillna(0)
        users_items_pivot_matrix = users_items_pivot_matrix_df.values
        users_ids = list(users_items_pivot_matrix_df.index)

        #Compressed Sparse Row matrix
        users_items_pivot_sparse_matrix = csr_matrix(users_items_pivot_matrix)

        # The number of factors to factor the user-item matrix.
        NUMBER_OF_FACTORS_MF = 15
        # Performs matrix factorization of the original user item matrix
        #U, sigma, Vt = svds(users_items_pivot_matrix, k = NUMBER_OF_FACTORS_MF)
        U, sigma, Vt = svds(users_items_pivot_sparse_matrix, k = NUMBER_OF_FACTORS_MF)

        sigma = np.diag(sigma)

        all_user_predicted_ratings = np.dot(np.dot(U, sigma), Vt)
        all_user_predicted_ratings_norm = (all_user_predicted_ratings - all_user_predicted_ratings.min()) / (all_user_predicted_ratings.max() - all_user_predicted_ratings.min())
        # Converting the reconstructed matrix back to a Pandas dataframe
        cf_preds_df = pd.DataFrame(all_user_predicted_ratings_norm, columns = users_items_pivot_matrix_df.columns, index=users_ids).transpose()
        #cf_preds_df.head(10)

        return cf_preds_df

    def recommend_items(self, user_id, items_to_ignore=[], topn=10, verbose=False):
        # Get and sort the user's predictions
        sorted_user_predictions = self.cf_predictions_df[user_id].sort_values(ascending=False) \
                                    .reset_index().rename(columns={user_id: 'recStrength'})

        # Recommend the highest predicted rating movies that the user hasn't seen yet.
        recommendations_df = sorted_user_predictions[~sorted_user_predictions['postId'].isin(items_to_ignore)] \
                               .sort_values('recStrength', ascending = False) \
                               .head(topn)

        if verbose:
            if self.items_df is None:
                raise Exception('"items_df" is required in verbose mode')

            recommendations_df = recommendations_df.merge(self.items_df, how = 'left',
                                                          left_on = 'postId',
                                                          right_on = 'postId')[['recStrength', 'postId', 'title', 'authorRegion', 'price']]

        return recommendations_df


import numpy as np
import matplotlib.pyplot as plt
from itertools import product

class BinomialTree:
    def __init__(self, S0, r, sigma, T, n):
        self.S0 = S0
        self.r = r
        self.sigma = sigma
        self.T = T
        self.n = n
        self.dt = self.T / self.n
        self.u = np.exp(self.sigma * np.sqrt(self.dt))
        self.d = 1./self.u
        self.p = (np.exp(self.r *self.dt) - self.d) / (self.u - self.d)

    def buildtree(self):
        S = np.zeros((self.n + 1, self.n + 1))
        S[0, 0] = self.S0
        for i in range(1, self.n + 1):
            S[i, 0] = S[i - 1, 0] * self.u
            for j in range(1, i + 1):
                S[i, j] = S[i - 1, j - 1] * self.d
        return S

    def tree2matrix(self):
        a = np.array(list(product((0, 1), repeat = self.n)))
        a = np.c_[[0] * 2 ** self.n, a]
        a = a.cumsum(axis = 1)
        return np.choose(a, self.buildtree().T)

    def putprice(self, K):
        putvalue = np.zeros((self.n + 1, self.n + 1))
        tree = self.buildtree()
        putvalue[self.n, :] = np.maximum(0, K - tree[self.n, :])
        for i in range(self.n - 1, -1, -1):
            for j in range(i + 1):
                putvalue[i, j] = max(0, K - tree[i, j], np.exp(-self.r * self.dt)*(self.p*putvalue[i+1, j] + (1 - self.p)*putvalue[i+1, j+1]))
        return putvalue

if __name__ == '__main__':
    print('This is a code for generate binomial tree and covert the paths to matrix')
    print("Let's see a basic example: ")
    S0, r, sigma, T, n = 36, 0.06, 0.2, 2, 15
    model = BinomialTree(S0, r, sigma, T, n)
    print('Now we are going to build a binomail tree:')
    tree = model.buildtree()
    print('Now we are going to convert to trajectories')
    trajectories = model.tree2matrix()
    plt.plot(trajectories.T)
    plt.show()
    print("let's calculate the american put option price from binomial tree")
    print('The American Put Option price is: ', model.putprice(40)[0,0])


import numpy as np
import rnp
import ransac

# test a single run of R6PLin on perfect perspective data
X = np.array([[-0.735203763665459, -0.496627573213431, -0.872484275284515, -0.427093140715349, -0.834433230284650,  -0.510357709134182], [0.238783627918357, -0.331469664458513, -0.774067735937978, -0.330087062598541, -0.532562868622104, -0.175836814526873], [0.348232082844991, 0.496786171364075, 0.842812754497372, 0.900023147138860, 0.062454513759772,0.920453051685240]])
u = np.array([[0.087573419907225, 0.234591535755890, -0.008470881920492,0.221656649106303, 0.020112962609198, 0.176817312337601], [0.377812297395972, -0.030443875680965, -0.260227638405494, -0.023394282943956, -0.225285886765297,  0.055631494170819]])

data = np.vstack((X,u))

res = rnp.r6pLin(data)
print("Camera center is:")
print(res[0][9:12])
print("Camera orientation in angle-axis representation is:")
print(res[0][6:9])
print("Camera rotation velocity is:")
print(res[0][0:3])
print("Camera translation velocity is:")
print(res[0][3:6])

# test R6PLin in LO-RANSAC on perfect perspective data
threshold = 1
maxiter = 10
result = ransac.loRansacSimple(rnp.r6pLin, rnp.calcR6PEAXErrFast, data, 6, threshold, 10, optimizeFn = rnp.calcR6PEAXErrFastForLsq, verbose = 1)


# This is an implementation from scratch of the logistic regression

# Algorithm of logistic regression
# The main goal of logistic regression is to find the best coefficients, and intercept
# to make the prediction accurate
import numpy as np
from exam import hours_studied, passed_exam

# For some reason np array that start with an int will only be an int
coefficients = np.array([[1.1]])
intercept = np.array([1.0])
learning_rate = 0.0001

def log_odds(features, coefficients, intercept):
  """Return the log odds for all the features"""
  return np.dot(features,coefficients) + intercept

def sigmoid(z):
    """Simulate the sigmoid function and return a result"""
    denominator = 1 + np.exp(-z)
    return 1/denominator

def log_loss(probabilities, actual_class, Xi):
    """Return a summed log loss of all values in the feature dataset"""
    return np.sum(-(1/actual_class.shape[0])*(actual_class*np.log(probabilities) + (1-actual_class)*np.log(1-probabilities))*Xi)

def get_error_rate(predicted, actual):
    """Return the average error rate"""
    error = 0
    for i in range(len(predicted)):
        error += abs(predicted[i][0] - actual[i][0])
    return error/len(predicted)

def train(features, labels):
    n = len(features)
    error_rate = 1
    i = 0
    print("Training Started!")
    while error_rate > 0:
        print(f"Iteration={i}")
        # First get the probabilities
        calculated_log_odds = log_odds(features, coefficients, intercept)
        probabilities = sigmoid(calculated_log_odds)
        # Calculate log loss
        logloss = log_loss(probabilities, labels, features)
        # Apply gradient descent algorithm
        derivative_sigmoid = (1/n) * logloss
        coefficients[0][0] = coefficients[0][0] - learning_rate*derivative_sigmoid
        intercept[0] = intercept[0] - learning_rate*derivative_sigmoid
        print(f"coefficient={coefficients},intercept={intercept}")
        # Calculate error rate
        result = np.where(probabilities >= 0.5, 1, 0)
        old_error_rate = error_rate
        error_rate = get_error_rate(result,labels)
        print(f"[debug]error_rate:{error_rate}")
        i += 1

# Create predict_class() function
def predict(features, threshold):
  calculated_log_odds = log_odds(features, coefficients, intercept)
  probabilities = sigmoid(calculated_log_odds)
  result = np.where(probabilities >= threshold, 1, 0)
  return result

# First, train the model
train(hours_studied, passed_exam)

# Make final classifications on Codecademy University data here
final_results = predict(hours_studied, 0.5)
predicted = final_results.tolist()
print(f"predicted: {predicted}")
actual = passed_exam.tolist()
print(f"realY_val: {actual}")


import numpy as np

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

def sigmoid_prime(x):
    return x*(1-x)

def relu(x):
    return x if x > 0 else 0

def relu_prime(x):
    return 1 if x > 0 else 0

class NeuralNet(object):
    def __init__(self, num_input, num_hidden_layers, num_neurons_per_layer, num_output, seed=-1):
        if seed != -1:
            np.random.seed(seed)
        self.weights = []

        self.weights.append(2*np.random.random((num_input, num_neurons_per_layer)) - 1)

        for i in xrange(num_hidden_layers-1):
            self.weights.append(2*np.random.random((num_neurons_per_layer, num_neurons_per_layer)) - 1)

        self.weights.append(2*np.random.random((num_neurons_per_layer, num_output)) - 1)

    def forward(self, inpt):
        past_input = [inpt]
        for weight in self.weights:
            past_input.append(sigmoid(np.dot(past_input[-1], weight)))

        return past_input

    def learn(self, inputs, outputs, rate):
        results = self.forward(inputs)

        deltas = []

        output_error = outputs - results[-1]
        deltas.append(output_error * sigmoid_prime(results[-1]))

        for index,result in enumerate(reversed(results[:-1])):
            error = np.dot(deltas[-1], self.weights[-index-1].T)
            deltas.append(error * sigmoid_prime(result))

        deltas.reverse()

        for index,weight in enumerate(self.weights):
            weight += np.dot(results[index].T, deltas[index+1]) * rate

    def error(self, inputs, outputs):
        results = self.forward(inputs)

        output_error = outputs - results[-1]

        return np.mean(np.abs(output_error))

    def output_dot(self, error=None):
        output = []
        output.append("digraph {")
        for index,weight in enumerate(self.weights):
            if index == 0:
                prefix = "I"
                nextprefix = "H"
            elif index == len(self.weights)-1:
                prefix = "H"
                nextprefix = "O"
            else:
                prefix = "H"
                nextprefix = "H"
            for row in xrange(weight.shape[0]):
                for col in xrange(weight.shape[1]):
                    output.append("{}{} -> {}{} [color=\"{},{},0.6\"]".format(
                        prefix, row,
                        nextprefix, col,
                        0.0 if np.sign(weight[row][col]) == -1 else 0.7,
                        round((sigmoid(np.abs(weight[row][col]))-0.5)*2, 4),
                    ))
        if error is not None:
            output.append("error [label=\"Error:\n{}%\", shape=plaintext]".format(round(self.error(error[0], error[1])*100, 2)))
            output.append("O0 -> error [style=invis]")
            output.append("O{} -> error [style=invis]".format(self.weights[-1].shape[1]-1))
        output.append("}")
        return "\n".join(output)


#T# linear equations in one variable contain only one variable and its exponent is 1, said variable can be repeated accross several different terms

#T# to simplify linear equations in one variable, the sympy package is used
import sympy

#T# the simplify function is used to simplify linear equations in one variable
x = sympy.Symbol('x')              # x
eq1 = sympy.Eq(6*x - 11, -3*x + 7) # Eq(6*x - 11, 7 - 3*x)
eq2 = sympy.simplify(eq1)          # Eq(x, 2)
#| when simplifying a linear equation in one variable, the simplification incidentally solves for the variable, the solution in this case is x = 2


#!/usr/bin/env python3
# vim: set ts=4:
#
# Assignment:	Image Enhancement and Filtering
# Course:		SCC0251
# Semester:		First of 2020
# Group:
#	<name>					<nUSP>
# 	***REMOVED***                       ***REMOVED***
#	***REMOVED***                       ***REMOVED***
#

import imageio
import math
import numpy as np

def pad_image(image, amount):
	h, w = image.shape						  # height, width
	nh, nw = h + amount * 2, w + amount * 2   # new values
	padded = np.zeros([nh, nw])
	padded[amount:amount + h, amount:amount + w] += image
	return padded

######################
## Bilateral filter ##
######################

def G(x, sigma):
	"""
Calculates a gaussian kernel"""
	return ((1 / (2 * math.pi * pow(sigma, 2))) *
			math.exp(-(pow(x, 2) / (2 * pow(sigma, 2)))))

def spatial_component(n, sigma):
	"""
Calculates the spatial gaussian kernel
Arguments:
	n	  -- filter size
	sigma -- variance"""
	center = int((n - 1) / 2) # index
	def dist(x, y):
		return math.sqrt(pow(x - center, 2) + pow(y - center, 2))
	matrix = np.zeros([n, n])
	for i in range(n):
		for j in range(n):
			matrix[i, j] = G(dist(i, j), sigma)
	return matrix

def range_component(region, n, sigma):
	"""
Calculates the range gaussian kernel of a region of the image
Arguments:
	region -- region of the image to use
	n	   -- filter size
	sigma  -- variance"""
	center = int((n - 1) / 2)
	pixel = region[center, center]
	matrix = np.zeros([n, n])
	for i in range(n):
		for j in range(n):
			Ii = region[i, j]
			matrix[i, j] = G(Ii - pixel, sigma)
	return matrix

def bilateral(image, n, sigma_s, sigma_r):
	"""
Bilateral Filter
Arguments:
	image -- input image
	n	  -- size of the filter
	σs	  -- space variance
	σr	  -- range variance"""

	gs = spatial_component(n, sigma_s)

	padding_needed = math.floor(n / 2)

	result = np.empty_like(image)
	working_area = pad_image(image, padding_needed)

	for i in range(image.shape[0]):
		for j in range(image.shape[1]):
			region = working_area[i:i + n, j:j + n]
			gr = range_component(region, n, sigma_r)
			w = gr * gs
			Wp = np.sum(w)
			If = np.sum(w * region)
			result[i, j] = If / Wp

	return result

####################
## Unsharp filter ##
####################

kernels = [
	np.array([[ 0, -1,	0], [-1,  4, -1], [ 0, -1,	0]]),
	np.array([[-1, -1, -1], [-1,  8, -1], [-1, -1, -1]])
]

def normalize(image):
	return ((image - np.min(image)) * 255) / (np.max(image) - np.min(image))

def unsharp(image, c, k):
	"""
Unsharp mask using the Laplacian Filter
Arguments:
	iamge -- input image
	c	  -- scaling factor
	k	  -- kernel to use"""
	n = 3	# kernels are n x n

	kernel = kernels[k - 1]

	working_area = pad_image(image, math.floor(n / 2))
	filtered = np.empty_like(image)

	# 1. Convolve original image with kernel, storing into `filtered`
	for i in range(image.shape[0]):
		for j in range(image.shape[1]):
			region = working_area[i:i + n, j:j + n]
			filtered[i, j] = np.sum(region * kernel)

	# 2. Scale the filtered image
	filtered = normalize(filtered)

	# 3. Add the filtered image, multiplied by c, to the original image
	result = filtered * c + image

	# 4. Scale the final image
	return normalize(result)

#####################
## Vignette filter ##
#####################

def gauss(x, sig):
	"""
	Samples the value at a single point from the Gaussian Curve, parameterized
	using the sig value as its sigma.
		x	- Relative positioning along the curve, which is centered at x = 0.
		sig - Sigma parameter.
	"""
	from math import pi as PI;
	from math import exp;
	return exp(-(x ** 2 / 2 * sig ** 2)) / (2 * PI * sig ** 2)

def vinagrette(img, sigma_row, sigma_col):
	"""
	Applies a vignette filter to a desired source image, returning the result.
		img		  - Source image.
		sigma_row - Sigma parameter for the curve along the vertical axis.
		sigma_col - Sigma parameter for the curve along the horizontal axis.
	"""
	width  = len(img[0])
	height = len(img)
	target = img.astype("float")
	maxval = None
	minval = None

	# Generate the combined gaussian matrix for the image and apply it as we go.
	# We also gather the minimum and maximum resulting values so that we can
	# normalize the results later on back to the 0-255 range.
	for i in range(height):
		for j in range(width):
			a = gauss(int(j - width  / 2), 1 / sigma_col)
			b = gauss(int(i - height / 2), 1 / sigma_row)
			target[i][j] *= a * b

			if maxval is None or target[i][j] > maxval: maxval = target[i][j]
			if minval is None or target[i][j] < minval: minval = target[i][j]

	# Normalize the image
	for i in range(height):
		for j in range(width):
			a = minval
			b = maxval
			c = 0
			d = 255
			target[i][j] = (target[i][j] - a) * ((d - c) / (b - a)) + c

	return target

###########################
## General functionality ##
###########################

def RSE(m, r):
	return math.sqrt(np.square(m - r).sum())

if __name__ == "__main__":
	filename = str(input()).rstrip()
	img = imageio.imread(filename).astype(np.float)
	method = int(input())
	save = int(input())

	if method == 1:
		n = int(input())
		sigma_s = float(input())
		sigma_r = float(input())
		output_img = bilateral(img, n, sigma_s, sigma_r)
	elif method == 2:
		c = float(input())
		k = int(input())
		output_img = unsharp(img, c, k)
	elif method == 3:
		sigma_row = float(input())
		sigma_col = float(input())
		output_img = vinagrette(img, sigma_row, sigma_col)
	else:
		raise Exception("Method " + str(method) + " unimplemented")

	output_img = output_img.astype(np.uint8)

	print("{0:.4f}".format(RSE(output_img, img)))

	if save == 1:
		imageio.imwrite("output_img.png", output_img)


import numpy as np
import iqplot
import bokeh.io
import bokeh
import scipy
import bebi103
import scipy.stats as st

def __ecdf(x, data):
    """Give the value of an ECDF at arbitrary points x

    Parameters
    __________
    x : array
    points to calculate ECDF for

    data : array
    input data to generate the ECDF based on

    Returns
    __________
    output : array of ECDF values for each point in x
    """
    y = np.arange(len(data) + 1) / len(data)
    return y[np.searchsorted(np.sort(data), x, side="right")]

def draw_bs_sample(data):
    '''Draw a boostrap sample from a 1D data set
    Parameters
    __________
    data : array
        input data to sample from

    Returns
    __________
    output: array
        new dataset drawn from the original dataset
    '''
    return np.random.choice(data, size = len(data))

def draw_bs_reps(data, stat_fun, size=1):
    '''Draw boostrap replicates computed with stat_fun from 1D dataset
    Parameters
    __________
    data : array
        input data to sample from
    stat_fun : function
        statistical function to calculate on each dataset replicate
    size : int, optional, default = 1
        number of dataset replicates to generate

    Returns
    __________
    output: array
        test statistic for each of size bootstrap replicate(s)
    '''
    return np.array([stat_fun(draw_bs_sample(data)) for _ in range (size)])

def draw_bs_reps_mean(data, size=1):
    '''Draw boostrap replicates of the mean from 1D data set
    Parameters
    __________
    data : array
        input data to sample from
    size : int, default = 1
        number of datasets to draw

    Returns
    __________
    output: array
        mean of new dataset drawn from the original dataset
    '''
    out = np.empty(size)
    for i in range(size):
        out[i] = np.mean(draw_bs_sample(data))
    return out

def draw_bs_reps_test_stat(x, y, size=1):
    """
    Generate bootstrap replicates with Kolmogrov Smirnov
    as the test statistic
    Parameters
    __________
    x : array
        input dataset 1 to sample from
    y : array
        input dataset 2

    Returns
    __________
    output: array
        Kolmogorov Smirnov test statistic for each trial
    """
    out = np.empty(size)
    for i in range(size):
        out[i] = st.ks_2samp(draw_bs_sample(x), draw_bs_sample(y))[0]

    return out

def __L(x, epsilon, data):
    '''Calculates L(x) for a given x value, epsilon, and data set

    Parameters
    ___________
    x : array
        points to calculate L(x) for
    epsilon : float
        epsilon value to use in equation
    data : array
        raw data

    Returns
    ___________
    output : array
        value of L(x) for each point in x
    '''
    ecdf_vals = __ecdf(x, data)

    return [max(0, val - epsilon) for val in ecdf_vals]

def __U(x, epsilon, data):
    '''Calculates U(x) for a given x value, epsilon, and data set
    x : array
        points to calculate U(x) for
    epsilon : float
        epsilon value to use in equation
    data : array
        raw data

    Returns
    ___________
    output : array
        value of U(x) for each point in x
    '''
    ecdf_vals = __ecdf(x, data)

    return [min(1, val + epsilon) for val in ecdf_vals]

def plot_conf_int(data, title, xlabel, color = 'green', palette = ["limegreen"]):
    ''' plots an ECDF with confidence intervals
    data : array
        contains raw data points from experiment
    title : string
        title for output graph
    xlabel : string
        x axis label for output graph
    color : string (optional)
        if given, color for upper and lower confidence interval bounds

    Returns
    ________
    output : bokeh figure
    '''
    x = np.linspace(0, max(data), 100)
    epsilon = np.sqrt(np.log(2/0.05)/(2 * len(data)))
    p = bokeh.plotting.figure(title=title, x_axis_label=xlabel,
                   y_axis_label='ECDF', width = 400, height = 400)
    l = __L(x, epsilon, data)
    u = __U(x, epsilon, data)
    p.line(x, l, color = color)
    p.line(x, u, color = color)
    # overlay with experimental ECDF
    iqplot.ecdf(data, p = p, conf_int = True, palette = palette)
    return p

def viz_compare_conf_int(data, data2, fun = np.mean, xlabel = "mean", title = "Comparison of Confidence Intervals",
                         label1 = "sample1", label2 = "sample2", size = 1000, color = "dimgray"):
    """Function to visualize overlap between two confidence intervals
    Parameters
    _________

    data : array
        first dataset
    data2 : array
        second dataset
    fun : statistical function (optional), default is mean
        if given, statistical function to calculate for each dataset
    label : string (optional), default is "mean"
        if given, used as axis label for confidence intervals graph
    size : int (optional), default = 1000
        number of samples for each dataset
    color : string (optional), default = "dimgray"
        if given, color of intervals in visualization

    Returns
    _________
    output : bokeh figure containing the visualization

    """
    bs_reps = draw_bs_reps(data, fun, size = size)
    bs_reps2 = draw_bs_reps(data2, fun, size = size)
    mean = np.mean(bs_reps)
    mean2 = np.mean(bs_reps2)
    conf_int = np.percentile(bs_reps, [2.5, 97.5])
    conf_int2 = np.percentile(bs_reps2, [2.5, 97.5])
    dict1 = {"estimate": mean, "conf_int": conf_int, "label" : label1}
    dict2 = {"estimate":mean2, "conf_int":conf_int2, "label" : label2}
    p = bebi103.viz.confints([dict1, dict2],
                             marker_kwargs = {"color":color},
                            line_kwargs = {"color":color})
    p.xaxis.axis_label = xlabel
    p.title.text = title
    return p


import numpy as np

def function_2(x):
    return x[0]**2 + x[1]**2

def numerical_gradient(f, x):
    h = 1e-4
    grad = np.zeros_like(x)

    for idx in range(x.size):
        tmp_val = x[idx]

        x[idx] = tmp_val + h
        fxh1 = f(x)

        x[idx] = tmp_val - h
        fxh2 = f(x)

        grad[idx] = (fxh1 - fxh2) / (2*h)
        x[idx] = tmp_val

    return grad

def gradient_descent(f, init_x, lr=0.01, step_num=1000):
    x = init_x

    for i in range(step_num):
        grad = numerical_gradient(f, x)
        x -= lr * grad

    return x

init_x = np.array([-3.,4.])
print(function_2(init_x))
print(numerical_gradient(function_2,init_x))
print(gradient_descent(function_2, init_x))


import numpy as np
import dill
import copy
from activation import sigmoid

class NeuralNetwork:
    def __init__(
        self, inputNum, hiddenNum, outputNum, activation=sigmoid,
    ):
        self.input_nodes = inputNum
        self.hidden_nodes = hiddenNum
        self.output_nodes = outputNum

        self.weights_ih = np.random.rand(self.hidden_nodes, self.input_nodes) * 2 - 1
        self.bias_h = np.random.rand(self.hidden_nodes, 1) * 2 - 1
        self.weights_ho = np.random.rand(self.output_nodes, self.hidden_nodes) * 2 - 1
        self.bias_o = np.random.rand(self.output_nodes, 1) * 2 - 1

        self.activation = np.vectorize(activation)

    def predict(self, input_list):
        inputs = np.asarray(input_list, float).reshape(-1, 1)

        hidden = np.matmul(self.weights_ih, inputs)
        hidden += self.bias_h
        hidden = self.activation(hidden)

        output = np.matmul(self.weights_ho, hidden)
        output += self.bias_o
        output = self.activation(output)

        return output.tolist()

    def serialize(self) -> bytes:
        return dill.dumps(self)

    @staticmethod
    def deserialize(data: bytes) -> "NeuralNetwork":
        return dill.loads(data)

    def mutate(self, func):
        func = np.vectorize(func)
        self.weights_ho = func(self.weights_ho)
        self.weights_ih = func(self.weights_ih)
        self.bias_o = func(self.bias_o)
        self.bias_h = func(self.bias_h)

    def copy(self):
        return copy.copy(self)


import math
from pysad.core.base_postprocessor import BasePostprocessor
from pysad.statistics.average_meter import AverageMeter
from pysad.statistics.running_statistic import RunningStatistic
from pysad.statistics.variance_meter import VarianceMeter
import numpy as np

class GaussianTailProbabilityCalibrator(BasePostprocessor):
    """Assuming that the scores follow normal distribution, this class provides an interface to convert the scores into probabilities via Q-function, i.e., the tail function of Gaussian distribution :cite:`ahmad2017unsupervised`.

        Args:
            running_statistics (bool): Whether to calculate the mean and variance through running window. The window size is defined by the `window_size` parameter.
            window_size (int): The size of window for running average and std. Ignored if `running_statistics` parameter is False.
    """

    def __init__(self, running_statistics=True, window_size=6400):
        self.running_statistics = running_statistics
        self.window_size = window_size

        if self.running_statistics:
            self.avg_meter = RunningStatistic(AverageMeter, self.window_size)
            self.var_meter = RunningStatistic(VarianceMeter, self.window_size)
        else:
            self.avg_meter = AverageMeter()
            self.var_meter = RunningStatistic(VarianceMeter, self.window_size)

    def fit_partial(self, score):
        """Fits particular (next) timestep's score to train the postprocessor.

        Args:
            score (float): Input score.
        Returns:
            object: self.
        """
        self.avg_meter.update(score)
        self.var_meter.update(score)

        return self

    def transform_partial(self, score):
        """Transforms given score.

        Args:
            score (float): Input score.

        Returns:
            float: Processed score.
        """
        mean = self.avg_meter.get()
        var = self.var_meter.get()
        if var > 0:
            std = np.sqrt(var)
        else:
            std = 1.0

        return 1 - self._qfunction(score, mean, std)

    def _qfunction(self, x, mean, std):
        """
        Given the normal distribution specified by the mean and standard deviation args, return the probability of getting samples > x. Implementation is adapted from the https://github.com/ish-vlad/Conformal-Anomaly-Detection/blob/22769b8d3cede7fabd978a36cdd2853255e450ac/scripts/nab_module/nab/detectors/gaussian/windowedGaussian_detector.py This is the
        Q-function: the tail probability of the normal distribution.
        """

        # Calculate the Q function with the complementary error function, explained
        # here:
        # http://www.gaussianwaves.com/2012/07/q-function-and-error-functions
        z = (x - mean) / std
        return 0.5 * math.erfc(z / math.sqrt(2))


import numpy as np
import matplotlib.pyplot as plt

N = 14
n = np.arange(N)
fn=(-1/2)**n
hn1=np.pad(fn, (0,2), 'constant', constant_values=(0))
hn2=np.pad(fn, (2,0), 'constant', constant_values=(0))
h = hn1+hn2

xtemp=np.array([1.0,2.0,3.0,4.0,2.0,1.0])
x=np.pad(xtemp, (0,8), 'constant', constant_values=(0))

X = np.zeros(N) + 1j*np.zeros(N)
for k in range(0,N):
	for n in range(0,N):
		X[k]+=x[n]*np.exp(-1j*2*np.pi*n*k/N)
H = np.zeros(N) + 1j*np.zeros(N)
for k in range(0,N):
	for n in range(0,N):
		H[k]+=h[n]*np.exp(-1j*2*np.pi*n*k/N)

Y = np.zeros(N) + 1j*np.zeros(N)
for k in range(0,N):
	Y[k] = X[k]*H[k]

y = np.zeros(N) + 1j*np.zeros(N)
for k in range(0,N):
	for n in range(0,N):
		y[k]+=Y[n]*np.exp(1j*2*np.pi*n*k/N)

#print(X)
y = np.real(y)/N
#plots
plt.stem(range(0,N),y)
plt.title('Filter Output using DFT')
plt.xlabel('$n$')
plt.ylabel('$y(n)$')
plt.grid()# minor

plt.savefig('yndft.png')


import math
from typing import List, Tuple

import numpy as np
from scipy import fftpack as sff
from scipy.special import erfc as erfc

class SpectralTest:

    @staticmethod
    def spectral_test(binary_data:str, verbose=False) -> List[Tuple[str, float, bool]]:
        """
        Note that this description is taken from the NIST documentation [1]
        [1] http://csrc.nist.gov/publications/nistpubs/800-22-rev1a/SP800-22rev1a.pdf
        The focus of this test is the peak heights in the Discrete Fourier Transform of the sequence. The purpose of
        this test is to detect periodic features (i.e., repetitive patterns that are near each other) in the tested
        sequence that would indicate a deviation from the assumption of randomness. The intention is to detect whether
        the number of peaks exceeding the 95 % threshold is significantly different than 5 %.

        :param      binary_data:        The seuqnce of bit being tested
        :param      verbose             True to display the debug messgae, False to turn off debug message
        :return:    (p_value, bool)     A tuple which contain the p_value and result of frequency_test(True or False)
        """
        length_of_binary_data = len(binary_data)
        plus_one_minus_one = []

        # Step 1 - The zeros and ones of the input sequence (ε) are converted to values of –1 and +1
        # to create the sequence X = x1, x2, …, xn, where xi = 2εi – 1.
        for char in binary_data:
            if char == '0':
                plus_one_minus_one.append(-1)
            elif char == '1':
                plus_one_minus_one.append(1)

        # Step 2 - Apply a Discrete Fourier transform (DFT) on X to produce: S = DFT(X).
        # A sequence of complex variables is produced which represents periodic
        # components of the sequence of bits at different frequencies
        spectral = sff.fft(plus_one_minus_one)

        # Step 3 - Calculate M = modulus(S´) ≡ |S'|, where S´ is the substring consisting of the first n/2
        # elements in S, and the modulus function produces a sequence of peak heights.
        slice = math.floor(length_of_binary_data / 2)
        modulus = abs(spectral[0:slice])

        # Step 4 - Compute T = sqrt(log(1 / 0.05) * length_of_string) the 95 % peak height threshold value.
        # Under an assumption of randomness, 95 % of the values obtained from the test should not exceed T.
        tau = math.sqrt(math.log(1 / 0.05) * length_of_binary_data)

        # Step 5 - Compute N0 = .95n/2. N0 is the expected theoretical (95 %) number of peaks
        # (under the assumption of randomness) that are less than T.
        n0 = 0.95 * (length_of_binary_data / 2)

        # Step 6 - Compute N1 = the actual observed number of peaks in M that are less than T.
        n1 = len(np.where(modulus < tau)[0])

        # Step 7 - Compute d = (n_1 - n_0) / sqrt (length_of_string * (0.95) * (0.05) / 4)
        d = (n1 - n0) / math.sqrt(length_of_binary_data * (0.95) * (0.05) / 4)

        # Step 8 - Compute p_value = erfc(abs(d)/sqrt(2))
        p_value = erfc(math.fabs(d) / math.sqrt(2))

        if verbose:
            print("Discrete Fourier Transform (Spectral) Test:")
            print("  {:<40}{:>20}".format("Length of Binary Data:", length_of_binary_data))
            print("  {:<40}{:>20}".format("Value of T:", tau))
            print("  {:<40}{:>20}".format("Value of n1:", n1))
            print("  {:<40}{:>20}".format("Value of n0:", n0))
            print("  {:<40}{:>20}".format("Value of d:", d))
            print("  {:<40}{:>20}".format("P-Value:", p_value))

        return [("spectral_test", p_value, (p_value >= 0.01))]


import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation, writers

# Set up formatting for the movie files
Writer = writers['ffmpeg']
writer = Writer(fps=20, metadata=dict(artist='Llew'), bitrate=1800)

xmin,xmax = -3,3
ymin,ymax = -20,20
fig, ax = plt.subplots(figsize=(10,8))
ydata= ydata2 = np.linspace(ymin,ymax, 1000)
ln, = plt.plot([], [], 'r.',
                    markersize=1.5,
                    animated=True,
                    label=r'x-nullcline: $x = \frac{y}{(\mu+y^2)}$')
ln2, = plt.plot([],[],
                    'b:',
                    lw=.5,
                    animated=True, label=r'y-nullcline: $x =  -\mu y + y^3}$')
ax.set_facecolor(plt.cm.gray(.95))
ax.set_title('Animation of Hopf Bifurcation for $\mu = \{-1.5 ... 3\}$')
ax.set_xlabel(r'$x$', size=14)
ax.set_ylabel(r'$y$', size=14)

def init():
    ax.set_xlim(xmin, xmax)
    ax.set_ylim(ymin, ymax)
    return ln, ln2,

def update(frame):
    xdata1 = ydata/(frame+ydata**2)
    xdata2 = -frame*ydata + ydata**3
    ln.set_data(ydata, xdata1)
    ln2.set_data(ydata,xdata2)
    return ln, ln2,

ani = FuncAnimation(fig, update, frames=np.linspace(-1.5,3, 500),
                    init_func=init, interval=60, blit=True)
plt.grid(True)
plt.legend()
#ani.save('Hopf_8_3_2.mp4', writer=writer)
plt.show()


## 2. ReLU Activation Function ##

import matplotlib.pyplot as plt

import numpy as np
x = np.linspace(-2, 2, 20)

def relu(x):
    return np.maximum(0,x)
relu_y = relu(x)
print(x)
print(relu_y)
plt.plot(x,relu_y)
plt.show()

## 3. Trigonometric Functions ##

x = np.linspace(-2*np.pi, 2*np.pi, 100)

tan_y =np.tan(x)
print(x, tan_y)
plt.plot(x, tan_y)

## 5. Hyperbolic Tangent Function ##

x = np.linspace(-40, 40, 100)
tanh_y = np.tanh(x)
print(x)
print(tanh_y)

plt.plot(x, tanh_y)

7. Machine Learning Intermediate/deep-learning-fundamentals/Nonlinear Activation Functions-242.py


import numpy as np
from numbers import Number

from ya_pca.rank_selection.noise_estimates import estimate_noise
from ya_pca.linalg_utils import svd_wrapper

def select_rank_rmt_threshold(X, thresh_method='dg',
                              noise_est='mp',
                              noise_est_kwargs={},
                              UDV=None):
    """
    Selects the PCA rank using one of the random matrix theory based thresholds.

    Parameters
    ----------
    X: array-like, (n_samples, n_features)
        The data matrix.

    thresh_method: str
        Which thesholding method to use. Must be one of
        'dg': Donoho-Gavish method

        'mpe': Marcenko Pastur edge method

    noise_est: float, str
        Either the noise estimate or a method to estimate the noise.

    noise_est_kwargs: dict
        Key word arguments for noise estimation method.

    UDV: None, tuple
        Precomputed SVD.

    Output
    ------
    rank_est, out

    rank_est: int
        Estimated rank

    out: dict
        All output from rank selection algorithm.
    """

    if UDV is None:
        UDV = svd_wrapper(X)

    if not isinstance(noise_est, Number):
        noise_est = estimate_noise(X, method=noise_est,
                                   UDV=UDV, **noise_est_kwargs)

    assert thresh_method in ['mpe', 'dg']

    if thresh_method == 'dg':
        thresh = donoho_gavish_threshold(shape=X.shape,
                                         sigma=noise_est)

    elif thresh_method == 'mpe':
        thresh = marcenko_pastur_edge_threshold(shape=X.shape,
                                                sigma=noise_est)

    svals = UDV[1]
    rank_est = sum(np.array(svals) > thresh)

    return rank_est, {'svals': svals,
                      'shape': X.shape,
                      'thresh': thresh,
                      'noise_estimate': noise_est}

def marcenko_pastur_edge_threshold(shape, sigma):
    """
    See (Gavish and Donoho, 2014).

    Parameters
    ----------
    shape: tuple (n_samples, n_features)
        Shape of the data matrix.

    sigma: float
        Estiamte of the noise standard deviation.

    Output
    ------
    sigular_value_threshold: float

    """
    n_samples, n_features = shape
    beta = n_features / n_samples
    mult = n_samples

    if beta > 1:
        beta = 1 / beta
        mult = n_features

    return (1 + np.sqrt(beta)) * np.sqrt(mult) * sigma

def dg_threshold(beta):
    return np.sqrt(2 * (beta + 1) + 8 * beta / (beta + 1 + np.sqrt(beta ** 2 + 14 * beta + 1)))

def donoho_gavish_threshold(shape, sigma):
    """
    (Gavish and Donoho, 2014)

    Parameters
    ----------
    shape: tuple (n_samples, n_features)
        Shape of the data matrix.

    sigma: float
        Estiamte of the noise standard deviation.

    Output
    ------
    sigular_value_threshold: float

    """
    n_samples, n_features = shape
    beta = n_features / n_samples
    mult = n_samples

    # TODO: is this what we want to do?
    if beta > 1:
        beta = 1 / beta
        mult = n_features

    if n_samples == n_features:
        lambd = 4 / np.sqrt(3)
    else:
        lambd = dg_threshold(beta)

    return lambd * np.sqrt(mult) * sigma


from pydeep.core import Function
import numpy as np

class Loss(Function):

    def backward(self):

        gx = self.cache["local_gx"]
        return gx

class CrossEntropyLoss(Loss):

    def forward(self, x, y):
        """
        Descr.: calculate the mean loss of the batch

        :param x:   final layer of the network (batch_size, n_dim),
                    no need for softmax as we calculate it here
        :param y:   truth values (batch_size, 1), each entry in the
                    array is the an integer indicating the class
                    of the data point
        :return:    the mean cross entropy loss of the batch
        """

        exp_x = np.exp(x)
        probs = exp_x / np.sum(exp_x, axis=1, keepdims=True)
        logprobs = -np.log([probs[i, y[i]] for i in range(len(probs))])
        crossentropy_loss = np.mean(logprobs)

        self.cache["probs"] = probs
        self.cache['y'] = y

        return crossentropy_loss

    def local_grad(self, x, y):
        """
        Descr.:     cache the local gradient for backprop.

        :param x:   final layer of the network (batch_size, n_dim),
                    no need for softmax as we calculate it here
        :param y:   truth values (batch_size, 1), each entry in the
                    array is the an integer indicating the class
                    of the data point
        """

        probs = self.cache["probs"]
        truth = np.zeros_like(probs)
        for i, j in enumerate(y):
            truth[i, j] = 1.0

        self.cache["local_gx"] = (probs - truth) / float(len(x))

class MSELoss(Loss):

    def forward(self, x, y):
        """
        Descr.:     calculate mean loss of the batch, the avg. loss of the current batch

        :param x:   predicted values, (batch_size, 1)
        :param y:   truth values, (batch_sze, 1)
        :return:    scalar value, the mse of the batch
        """
        loss = ((x - y)**2).mean()
        return loss

    def local_grad(self, x, y):
        """
        Descr.: calulate dL/dx, and cache it for backprop.

        :param x: predicted values, (batch_size, 1)
        :param y: truth values, (batch_sze, 1)
        """
        self.cache["local_gx"] = 2 * (x - y) / x.shape[0]


"""Rotating cartesian points that live on the unit sphere
around a random or specified axis by a random or specified amount"""
from numpy.random import rand, randn
from numpy import zeros, cos, sin, pi, multiply, matmul
from numpy.linalg import norm

# pylint: disable=C0103

def rotate(axis, angle, xyz):
    """Rotates xyz around axis by angle."""
    rot = rotationmatrix(axis, angle)
    if len(xyz.shape) == 1:  # just one point
        if not len(xyz) == 3:
            raise ValueError("Points have to either be of shape (3,) or (n,3). ")
        return multiply(rot, xyz)
    if len(xyz.shape) == 2:
        # we assume xyz to be of shape n x 3
        if not xyz.shape[1] == 3:
            raise ValueError("Points have to either be of shape (3,) or (n,3). ")

        return matmul(rot, xyz.T).T

    raise ValueError("Points have to either be of shape (3,) or (n,3). ")

def randomaxisrotate(angle, xyz):
    """Rotates xyz around a random axis by angle."""

    # get random point on unit sphere
    axis = randn(3)
    axis = axis / norm(axis)
    return rotate(axis, angle, xyz)

def randomanglerotate(axis, xyz):
    """Rotates xyz around axis by a random angle."""
    angle = 2 * pi * rand()
    return rotate(axis, angle, xyz)

def randomrotate(xyz):
    """Rotates xyz around a random axis by a random angle."""
    # get random point on unit sphere
    axis = randn(3)
    axis = axis / norm(axis)
    angle = 2 * pi * rand()
    return rotate(axis, angle, xyz)

def rotationmatrix(axis, angle):
    """Returns the rotation matrix of size 3x3 that rotates a point
    around axis by angle.
    See: https://en.wikipedia.org/wiki/Rotation_matrix
    """
    ux = axis[0]
    uy = axis[1]
    uz = axis[2]

    costheta = cos(angle)
    sintheta = sin(angle)
    rot = zeros((3, 3))

    rot[0, 0] = ux * ux * (1 - costheta) + costheta
    rot[0, 1] = ux * uy * (1 - costheta) - uz * sintheta
    rot[0, 2] = ux * uz * (1 - costheta) + uy * sintheta

    rot[1, 0] = uy * ux * (1 - costheta) + uz * sintheta
    rot[1, 1] = uy * uy * (1 - costheta) + costheta
    rot[1, 2] = uy * uz * (1 - costheta) - ux * sintheta

    rot[2, 0] = uz * ux * (1 - costheta) - uy * sintheta
    rot[2, 1] = uz * uy * (1 - costheta) + ux * sintheta
    rot[2, 2] = uz * uz * (1 - costheta) + costheta

    return rot


#
# line segment intersection using vectors
# see Computer Graphics by F.S. Hill
#
from numpy import *
import sys

def perp( a ) :
    b = empty_like(a)
    b[0] = -a[1]
    b[1] = a[0]
    return b

# line segment a given by endpoints a1, a2
# line segment b given by endpoints b1, b2
# return
def intersectPoint( a1,a2, b1,b2 ) :
    a1 = array(a1)
    a2 = array(a2)
    b1 = array(b1)
    b2 = array(b2)
    da = a2-a1
    db = b2-b1
    dp = a1-b1
    dap = perp(da)
    denom = dot( dap, db)
    if not denom : return None
    num = dot( dap, dp )
    return (num / denom.astype(float))*db + b1

def isBetween( a, b, c):
    a = array(a)
    b = array(b)
    c = array(c)
    cma = c-a
    bma = b-a
    crossproduct = cma[1]*bma[0] - cma[0]*bma[1]
    if abs(crossproduct) > finfo(float32).eps:
        #print 'crossFail', abs(crossproduct), finfo(float32).eps
        return False

    dotproduct = cma[0]*bma[0] + cma[1]*bma[1]
    if dotproduct < 0:
        #print 'dotFail', dotProduct
        return False
    squaredLength = pow( bma[0], 2) + pow( bma[1], 2 )
    if dotproduct > squaredLength:
        #print 'squareFail',dotproduct,  squaredLength
        return False

    return True

def intersect( a1,a2, b1,b2 ) :
    point = intersectPoint( a1,a2, b1,b2 )
    #print 'point', point
    if point is None: return None

    #print 'a', isBetween(a1, a2, point)
    #print 'b', isBetween(b1, b2, point)
    if not isBetween(a1, a2, point): return None
    if not isBetween(b1, b2, point): return None

    return point

def dist( a,b, c ) :
    a = array(a)
    b = array(b)
    c = array(c)

    lineA = a-b
    lineADist = sqrt( pow(lineA[0], 2) + pow(lineA[1], 2) )
    lineB = a-c
    lineBDist = sqrt( pow(lineB[0], 2) + pow(lineB[1], 2) )

    print 'dists', lineADist, lineBDist
    return lineBDist/lineADist


"""
Specific useful functions.
"""

from __future__ import division
from ..utils.py3 import textstring

import numpy as np

### Kernels ###

def gaussian_k(x, sigma=1., height=None):
    """
    Gaussian kernel function.

    Normalized by the area if `height` is ``None``, otherwise `height` is the value at 0.
    """
    if height is None:
        return 1./np.sqrt(2*np.pi*sigma**2)*np.exp(-(x**2)/(2.*sigma**2))
    else:
        return np.exp(-x**2/(2.*sigma**2))*height

def rectangle_k(x, width=1., height=None):
    """"
    Symmetric rectangle kernel function.

    Normalized by the area if `height` is ``None``, otherwise `height` is the value at 0.
    """
    if height is None:
        return (abs(x)<width)/(2.*width)
    else:
        return (abs(x)<width)*height

def lorentzian_k(x, gamma=1., height=None):
    """
    Lorentzian kernel function

    Normalized by the area if `height` is ``None``, otherwise `height` is the value at 0.
    """
    if (height is None):
        return gamma/(x**2+(gamma/2.)**2)/np.pi
    else:
        return (gamma/2.)**2/(x**2+(gamma/2.)**2)*height

def complex_lorentzian_k(x, gamma=1., amplitude=1.j):
    """
    Complex Lorentzian kernel function.
    """
    return (gamma/2.)/(gamma/2.+1j*x)*amplitude

def exp_decay_k(x, width=1., height=None, mode="causal"):
    """
    Exponential decay kernel function

    Normalized by area if ``height=None`` (if possible), otherwise `height` is the value at 0.

    Mode determines value for ``x<0``:
        - ``'causal'`` - it's 0 for ``x<0``;
        - ``'step'`` - it's constant for ``x<=0``;
        - ``'continue'`` - it's a continuous decaying exponent;
        - ``'mirror'`` - function is symmetric: ``exp(-|x|/width)``.
    """
    if mode=="causal":
        if height is None:
            return (x>=0)*np.exp(-x/float(width))/width
        else:
            return (x>=0)*np.exp(-x/float(width))*height
    elif mode=="step":
        if height is None:
            return ((x>=0)*np.exp(-x/float(width))+(x<0)*1.)/width
        else:
            return ((x>=0)*np.exp(-x/float(width))+(x<0)*1.)*height
    elif mode=="continue":
        if height is None:
            return np.exp(-x/float(width))/width
        else:
            return np.exp(-x/float(width))*height
    elif mode=="mirror":
        if height is None:
            return np.exp(-np.abs(x)/float(width))/width
        else:
            return np.exp(-np.abs(x)/float(width))*height

_kernel_functions={"gaussian":gaussian_k, "rectangle":rectangle_k, "lorentzian":lorentzian_k, "exp_decay":exp_decay_k,
                   "complex_lorentzian":complex_lorentzian_k}
def get_kernel_func(kernel):
    """
    Get a kernel function by its name.

    Available functions are: ``'gaussian'``, ``'rectangle'``, ``'lorentzian'``, ``'exp_decay'``, ``'complex_lorentzian'``.
    """
    if isinstance(kernel,textstring):
        try:
            return _kernel_functions[kernel]
        except KeyError:
            raise ValueError("unrecognized kernel name: "+kernel)
    else:
        return kernel

### Windows ###
# TODO: different compensations (total power, peak height, etc.?)
def rectangle_w(x, N, ft_compensated=False):
    """
    Rectangle FT window function.
    """
    return x*0+1

def gen_hamming_w(x, N, alpha, beta, ft_compensated=False):
    """
    Generalized Hamming FT window function.

    If ``ft_compensated==True``, multiply the window function by a compensating factor to preserve power in the spectrum.
    """
    if ft_compensated:
        return (alpha-beta*np.cos(2*np.pi*x/(N-1)))/np.sqrt(alpha**2+beta**2/2.)
    else:
        return alpha-beta*np.cos(2*np.pi*x/(N-1))

def hann_w(x, N, ft_compensated=False):
    """
    Hann FT window function.

    If ``ft_compensated==True``, multiply the window function by a compensating factor to preserve power in the spectrum.
    """
    return gen_hamming_w(x,N,0.5,0.5,ft_compensated=ft_compensated)

def hamming_w(x, N, ft_compensated=False):
    """
    Specific Hamming FT window function.

    If ``ft_compensated==True``, multiply the window function by a compensating factor to preserve power in the spectrum.
    """
    return gen_hamming_w(x,N,0.54,0.46,ft_compensated=ft_compensated)

_window_functions={"hamming":hamming_w, "rectangle":rectangle_w, "hann":hann_w}
def get_window_func(window):
    """
    Get a window function by its name.

    Available functions are: ``'hamming'``, ``'rectangle'``, ``'hann'``.
    """
    if isinstance(window,textstring):
        try:
            return _window_functions[window]
        except KeyError:
            raise ValueError("unrecognized window name: "+window)
    else:
        return window

def gen_hamming_w_ft(f, t, alpha, beta):
    """
    Get Fourier Transform of a generalized Hamming FT window function.

    `f` is the argument, `t` is the total window size.
    """
    lim=beta/(2.*alpha)
    gen=np.sinc(f*t)*(1-(f*t)**2 *(alpha-beta)/alpha)/(1-(f*t)**2)
    if isinstance(gen,np.ndarray):
        return np.where(f*t==1,lim,gen)
    return lim if f*t==1 else gen

def rectangle_w_ft(f, t):
    """
    Get Fourier Transform of the rectangle FT window function.

    `f` is the argument, `t` is the total window size.
    """
    return gen_hamming_w_ft(f,t,1.,0.)

def hann_w_ft(f, t):
    """
    Get Fourier Transform of the Hann FT window function.

    `f` is the argument, `t` is the total window size.
    """
    return gen_hamming_w_ft(f,t,.5,.5)

def hamming_w_ft(f, t):
    """
    Get Fourier Transform of the specific Hamming FT window function.

    `f` is the argument, `t` is the total window size.
    """
    return gen_hamming_w_ft(f,t,.54,.46)

_window_ft_functions={"hamming":hamming_w_ft, "rectangle":rectangle_w_ft, "hann":hann_w_ft}
def get_window_ft_func(window):
    """
    Get a Fourier Transform of a window function by its name.

    Available functions are: ``'hamming'``, ``'rectangle'``, ``'hann'``.
    """
    if isinstance(window,textstring):
        try:
            return _window_ft_functions[window]
        except KeyError:
            raise ValueError("unrecognized window name: "+window)
    else:
        return window


import environment
import random
import copy
import numpy as np
import time

class N_QueenProblem():
    def __init__(self, n):
        self.env = environment.Environment(n)
        self.size = n
        self.current_state = ()
        self._random_generate()
        self.cost_map = dict({})
        random.seed(time.time())
        return

    def move(self, ori, new):
        tmp = self.env.grid[new[0]][new[1]]
        self.env.grid[new[0]][new[1]] = self.env.grid[ori[0]][ori[1]]
        self.env.grid[ori[0]][ori[1]] = tmp
        pass

    def cost(self, state=None):
        '''
        Calculate the cost of a given state.

        Input
        - state: a state of the n-queen problem

        Output
        - total_state: the cost of the state
        '''
        if state is None:
            state = self.current_state

        if (state) in self.cost_map.keys():
            return self.cost_map[state]
        else:
            total_cost = 0
            grid = np.zeros((self.size, self.size), dtype=int)
            for q in state:
                grid[q] = 1
            for i in range(self.size):
                n = np.count_nonzero(grid[i, :])
                if n >= 2:
                    total_cost += self._factorial(n) / (self._factorial(2)*self._factorial(n-2))

                n = np.count_nonzero(grid[:, i])
                if n < 2:
                    continue
                total_cost += self._factorial(n) / (self._factorial(2)*self._factorial(n-2))

            for k in range(self.size):
                dia = [grid[i+k, i] for i in range(self.size-k)]
                n = dia.count(1)
                if n >= 2:
                    total_cost += self._factorial(n) / (self._factorial(2)*self._factorial(n-2))

            for k in range(1, self.size):
                dia = [grid[i, i+k] for i in range(self.size-k)]
                n = dia.count(1)
                if n >= 2:
                    total_cost += self._factorial(n) / (self._factorial(2)*self._factorial(n-2))

            for k in range(self.size):
                dia = [grid[-i-k-1, i] for i in range(self.size-k)]
                n = dia.count(1)
                if n >= 2:
                    total_cost += self._factorial(n) / (self._factorial(2)*self._factorial(n-2))

            for k in range(1, self.size):
                dia = [grid[-i-1, i+k] for i in range(self.size-k)]
                n = dia.count(1)
                if n >= 2:
                    total_cost += self._factorial(n) / (self._factorial(2)*self._factorial(n-2))

            self.cost_map[state] = int(total_cost)
            return int(total_cost)

    def get_successors(self, state=None):
        successors = []
        if state is None:
            state = self.current_state

        for i in range(self.size):
            avai = list(range(self.size))
            avai.remove(state[i][1])
            for j in avai:
                succ = list(copy.deepcopy(state))
                succ[i] = (succ[i][0], j)
                successors.append(tuple(succ))
        return successors

    def show(self):
        self.env.show()
        return

    def _random_generate(self):
        for i in range(self.size):
            rand = random.randint(0, self.size-1)
            self.current_state += ((i, rand), )
            self.env.grid[i][rand] = 1
        return

    def _combination(self, n):
        total_cost = 0
        total_cost += self._factorial(n) / (self._factorial(2)*self._factorial(n-2))
        return int(total_cost)

    def _factorial(self, n, com=1):
        if n >= 1:
            return self._factorial(n-1, com*n)
        return com

if __name__ == '__main__':
    prob = N_QueenProblem(8)
    # print(prob._combination(1))
    prob.show()
    print('cost =', prob.cost())
    # print(len(prob.get_successors()))


from numpy import (
    array,  # for numpy arrays
    dot,  # for matrix multiplication
    exp,  # used to find sigmoid function
    random  # for random number generation
)

class SimpleNeuralNetwork:
    def __init__(self, dimensions):
        """ initializing weights based on dimensions count """
        weights = list()
        for i in range(dimensions):
            weights.append([random.random()])
        self.weights = array(weights)

    @staticmethod
    def sigmoid_func(val):
        """ Sigmoid Function """
        return 1 / (1 + exp(-val))

    @staticmethod
    def sigmod_func_derivative(prediction):
        """ derivative of Sigmoid Function """
        return prediction * (1 - prediction)

    def predict(self, pred_vals):
        """ sigmoid(sum(each point * its weight)) """
        return self.sigmoid_func(dot(pred_vals, self.weights))

    def train(self, input_x, input_y, iterations):
        """ predicting, finding error, updating weights, start over """
        for _ in range(iterations):
            # predicting with current weights
            prediction = self.predict(input_x)

            # difference in actual output and current output
            error = input_y - prediction

            # updating weights with gradient based on error value
            self.weights += dot(input_x.T, error * self.sigmod_func_derivative(prediction))

if __name__ == '__main__':
    """ simple example usecase for above module """
    # independent variables for training
    train_x = array([
        [0, 0],
        [1, 1],
        [1, 0],
        [0, 1]
    ])
    # dependent variables for training
    train_y = array([
        [0],
        [1],
        [1],
        [0]
    ])

    # initialise neural network model with random weights
    nn = SimpleNeuralNetwork(dimensions=2)
    # train the models (update weights based on independent & dependent variables)
    nn.train(train_x, train_y, 100)

    test_x = array([1, 0])  # independent variables for testing
    # predicting dependent variables from independent variables
    test_y = nn.predict(test_x)
    print(test_x, '=>', test_y)


# Ad Soyad: Batuhan Okur    Numara: 180401011
from sympy import Symbol

def polinomaUydurma(pDerece,vakalar): # Polinomun derecesini ve verileri alarak polinoma uydurma işlemini yapar ve korelasyon katsayısını bularak en uygun polinomu seçer.
    matris = []
    temp = 0
    for i in range(pDerece+1):
        satir = []
        for j in range(pDerece+1):
            toplam = 0
            for k in range(1,len(vakalar)+1):
                toplam += k**temp
            satir.append(toplam)
            temp += 1
        matris.append(satir)
        temp -= pDerece
    sonuc = []
    for i in range(pDerece+1):
        toplam = 0
        for j in range(len(vakalar)):
            toplam += vakalar[j]*(j+1)**i
        sonuc.append(toplam)
    for i in range(pDerece+1):
        b = matris[i][i]
        for j in range(i+1,pDerece+1):
            bolum = b/matris[j][i]
            sonuc[j] = sonuc[j]*bolum-sonuc[i]
            for k in range(pDerece+1):
                matris[j][k] = matris[j][k]*bolum-matris[i][k]
    for i in range(pDerece,-1,-1):
        b = matris[i][i]
        for j in range(i-1,-1,-1):
            bolum = b/matris[j][i]
            sonuc[j] = sonuc[j]*bolum-sonuc[i]
            for k in range(pDerece+1):
                matris[j][k] = matris[j][k]*bolum-matris[i][k]
    for i in range(pDerece+1):
        sonuc[i] = sonuc[i]/matris[i][i]
    yOrt=0
    for i in range (len(vakalar)):
        yOrt += vakalar[i]
    yOrt = yOrt/len(vakalar)
    St=0
    Sr=0
    for i in range(len(vakalar)):
        x = vakalar[i]
        St +=(vakalar[i]-yOrt)**2
        for j in range(len(sonuc)):
            x -= sonuc[j]*(i+1)**j
        x=x**2
        Sr += x
    korelasyon = ((St-Sr)/St)**(1/2)
    return sonuc,korelasyon

def uygunPolinomDerecesiDondur(katsayilar):
    maksimumEleman = max(katsayilar)
    for i in range(len(katsayilar)):
        if katsayilar[i] == maksimumEleman:
            derece = i
    return derece

def polinomluIntegralBul(polinomlar):
    x = Symbol('x')
    polinom = 0
    for i in range(len(polinomlar)):
        polinom += polinomlar[i] * (x ** i)
    a,b=1,len(vakalar) #18040101(1)
    integral = 0
    deltax = 1
    n = int((b-a)/deltax)
    for j in range(n):
        integral += deltax * (polinom.subs({x: a}) + polinom.subs({x: a+deltax}))/2
        a += deltax
    return integral,polinom

def polinomsuzİntegralBul(veriler):
    a,b=1,len(veriler) #18040101(1)
    integral = 0
    deltax = 1
    n = int((b-a)/deltax)
    for i in range(n-1):
        integral += deltax * (veriler[a] + veriler[a+deltax])/2
        a += deltax
    return integral

def yorumYap(dosya):
    yorum = "Batuhan Okur / 180401011 \n " \
            "Integral hesaplarken hesapladığımız polinomu dikdörtgenlere böler ve bu dikdörtgenlerin alanlarını hesaplayıp toplarız.\n" \
            "Bu dikdörtgenlerin eni ne kadar küçük olursa sonuç o kadar gerçeğe yakın olur. \n" \
            "Fakat bu hesaplanan iki fonksiyonda da dikdörtgenin eni(deltax) eşit alındı ve farklı sonuç çıktı. \n" \
            "Bunun sebebi bulduğumuz 6. dereceden polinomun orjinal polinoma belirli bir hata oranı olacak şekilde yakın olmasıdır." \
            "Eğer orjinal polinomu elde etmiş olsaydık(korelasyon katsayısı 1 olsaydı) sonuçlar aynı çıkacaktı."
    yorumDosyasi = open(dosya,"w")
    yorumDosyasi.write(yorum)
    yorumDosyasi.close()

#main(işlemlerin yapıldığı) kısım
dosya = open("veriler.txt","r")
vakalar = dosya.readlines()
for i in range(len(vakalar)):
    vakalar[i]=int(vakalar[i])
polynoms, korelasyonlar = [0] * 6, [0] * 6
for indis in range(0, 6):
    polynoms[indis], korelasyonlar[indis] = polinomaUydurma(indis+1, vakalar)
dosya.close()
uygunPolinomDerecesi = uygunPolinomDerecesiDondur(korelasyonlar)
print("Verilere en uygun polinomun derecesi : ",uygunPolinomDerecesi+1)
polinomluIntegral,kullanilanPolinom = polinomluIntegralBul(polynoms[uygunPolinomDerecesi])
print("\nKullanılan polinom : ",kullanilanPolinom)
print("\nPolinom kullanarak bulunan integral : ",polinomluIntegral)
polinomsuzİntegral = polinomsuzİntegralBul(vakalar)
print("\nPolinom kullanmadan bulunan integral : ",polinomsuzİntegral)
yorumYap('180401011_yorum.txt')


import numpy as np
import submission as sub
import numpy.linalg as la

# 1. Generate random camera matrix

K = np.array([[1,0,100], [0,1,100], [0,0,1]])
R, _,_ = la.svd(np.random.randn(3,3))
if la.det(R) < 0: R = -R
t = np.vstack((np.random.randn(2,1), 1))

P = K @ np.hstack((R, t))

# 2. Generate random 2D and 3D points

N = 100

X = np.random.randn(N,3)
x = P @ np.hstack((X, np.ones((N,1)))).T
x = x[:2,:].T / np.vstack((x[2,:], x[2,:])).T

# 3. Test pose estimation with clean points

Pc = sub.estimate_pose(x, X)

xp = Pc @ np.hstack((X, np.ones((N,1)))).T
xp = xp[:2,:].T / np.vstack((xp[2,:], xp[2,:])).T

print('Reprojection Error with clean 2D points:', la.norm(x-xp))
print('Pose Error with clean 2D points:', la.norm((Pc/Pc[-1,-1])-(P/P[-1,-1])))

# 4. Test pose estimation with noisy points

x = x + np.random.rand(x.shape[0], x.shape[1])
Pn = sub.estimate_pose(x, X)

xp = Pn @ np.hstack((X, np.ones((N,1)))).T
xp = xp[:2,:].T / np.vstack((xp[2,:], xp[2,:])).T

print('Reprojection Error with noisy 2D points:', la.norm(x-xp))
print('Pose Error with noisy 2D points:', la.norm((Pn/Pn[-1,-1])-(P/P[-1,-1])))


from math import (
    atan2,
    sqrt,
    cos,
    sin,
    pi,
)

import cv2
import numpy as np

def get_orientation(pts, img):
    sz = len(pts)
    data_pts = np.empty((sz, 2), dtype=np.float64)
    for i in range(data_pts.shape[0]):
        data_pts[i, 0] = pts[i, 0, 0]
        data_pts[i, 1] = pts[i, 0, 1]
    # Perform PCA analysis
    mean = np.empty(0)
    mean, eigenvectors, eigenvalues = cv2.PCACompute2(data_pts, mean)
    # Store the center of the object
    cntr = (int(mean[0, 0]), int(mean[0, 1]))
    cv2.circle(img, cntr, 3, (255, 0, 255), 2)
    p1 = (
        cntr[0] + 0.02 * eigenvectors[0, 0] * eigenvalues[0, 0],
        cntr[1] + 0.02 * eigenvectors[0, 1] * eigenvalues[0, 0])
    p2 = (
        cntr[0] - 0.02 * eigenvectors[1, 0] * eigenvalues[1, 0],
        cntr[1] - 0.02 * eigenvectors[1, 1] * eigenvalues[1, 0])
    draw_axis(img, cntr, p1, (0, 150, 0), 50)
    draw_axis(img, cntr, p2, (200, 150, 0), 50)
    angle = atan2(eigenvectors[0, 1], eigenvectors[0, 0])  # orientation in radians
    return angle

def draw_axis(img, p_, q_, colour, scale):
    p = list(p_)
    q = list(q_)
    angle = atan2(p[1] - q[1], p[0] - q[0])  # angle in radians
    hypotenuse = sqrt((p[1] - q[1]) * (p[1] - q[1]) + (p[0] - q[0]) * (p[0] - q[0]))
    # Here we lengthen the arrow by a factor of scale
    q[0] = p[0] - scale * hypotenuse * cos(angle)
    q[1] = p[1] - scale * hypotenuse * sin(angle)
    cv2.line(img, (int(p[0]), int(p[1])), (int(q[0]), int(q[1])), colour, 1, cv2.LINE_AA)
    # create the arrow hooks
    p[0] = q[0] + 9 * cos(angle + pi / 4)
    p[1] = q[1] + 9 * sin(angle + pi / 4)
    cv2.line(img, (int(p[0]), int(p[1])), (int(q[0]), int(q[1])), colour, 1, cv2.LINE_AA)
    p[0] = q[0] + 9 * cos(angle - pi / 4)
    p[1] = q[1] + 9 * sin(angle - pi / 4)
    cv2.line(img, (int(p[0]), int(p[1])), (int(q[0]), int(q[1])), colour, 1, cv2.LINE_AA)


"""
Suppose you have some function f(x)=exp(-x) on the range x in [0, 1].

You want to pick n points to linearly interpolate this such that the L2-error is minimized. How do you do it?
"""
import numpy as np
import casadi as cas
import matplotlib.pyplot as plt

opti = cas.Opti()

n = 101

x = opti.variable(n)  # cas.linspace(0,1,n)

opti.set_initial(x, cas.linspace(0, 10, n))

opti.subject_to([
    x[0] == 0,
    x[-1] == 10,
])

y = cas.exp(-x)

x1 = x[:-1]
x2 = x[1:]
errors = -x1 * cas.exp(-x2) / 2 - x1 * cas.exp(-x1) / 2 + x2 * cas.exp(-x2) / 2 + x2 * cas.exp(-x1) / 2 + cas.exp(
    -x2) - cas.exp(-x1)
error = cas.sum1(errors)

opti.minimize(error * 1e3)
opti.solver('ipopt')
sol = opti.solve()

xopt = sol.value(x)
minerror = sol.value(error)


#!/usr/bin/env python
# coding: utf-8

# # Initial Value Non-Homogeneous Linear ODE Example
#
# **Randall Romero Aguilar, PhD**
#
# This demo is based on the original Matlab demo accompanying the  Computational Economics and Finance 2001 textbook by Mario Miranda and Paul Fackler.
#
# Original (Matlab) CompEcon file: **demode03.m**
#
# Running this file requires the Python version of CompEcon. This can be installed with pip by running
#
#     !pip install compecon --upgrade
#
# Last updated: 2021-Oct-01
#

# ## About
#
# Solve
# \begin{align*}
# \dot{x_1} &= x_1 +12x_2 - 60\\
# \dot{x_2} &= -x_1 - 6x_2 + 36
# \end{align*}
#
# subject to
#
# \begin{align*}
# x_1(0) &=5\\
# x_2(1) &=2\\
#   t &\in [0, 3]
# \end{align*}

# ## FORMULATION

# In[1]:

from compecon import jacobian, ODE

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

# ### Phase Diagram Title and Axis Labels

# In[2]:

xlabels  = ['$x_1$', '$x_2$']

# ### Velocity Function

# In[3]:

A  = np.array([[1, 12],[-1, -6]])
b  = np.array([-60,36])

def f(x, A, b):
    return ((A @ x).T + b).T

# ### Closed-Form Solution

# In[4]:

def X(t):
    return pd.DataFrame({xlabels[0]: 12 - 48*np.exp(-2*t) + 42*np.exp(-3*t),
                  xlabels[1]: 4 + 12*np.exp(-2*t) - 14*np.exp(-3*t)},
                 index = t)

# ### Initial State

# In[5]:

xinit = np.array([6,2])

# ### Time Horizon

# In[6]:

T = 3

# ## SOLVE ODE ANALYTICALLY

# In[7]:

# Time Discretization
N = 100              # number of time nodes
t = np.linspace(0,T, N)  # time nodes

# Plot Closed-Form Solution in Time Domain
fig, ax= plt.subplots()
X(t).plot(ax=ax)
ax.set(title='Solution', xlabel='Time')

# ## SOLVE ODE USING RUNGE-KUTTA METHOD (RK4)

# In[8]:

# Solve ODE
problem = ODE(f, T, xinit, A, b, labels=xlabels)

problem.rk4(n=N)
problem.x.plot()

# In[9]:

# Plot Runge-Kutta Approximation Errors
fig, ax = plt.subplots()
(problem.x - X(problem.x.index)).plot(ax=ax)
ax.axhline(0,color='black', ls=':')
ax.set(title='Runge Kutta Approximation Errors', xlabel='Time', ylabel='Error')

# In[10]:

problem.x.plot()

# ### SOLVE ODE USING COLLOCATION METHOD (ODECOL)

# In[11]:

# Solve ODE
n  = 20;    # number of basis functions
problem.solve_collocation(n=n)

# Plot Collocation Approximation Errors
fig, ax = plt.subplots()
t = problem.x.index
(problem.x - X(t)).plot(ax=ax)
ax.axhline(0,color='black', ls=':')

ax.set(title='Collocation Approximation Errors',
       xlabel='Time',
       ylabel='Error')

# ### STEADY-STATE

# In[12]:

# Compute Steady State
xstst = -np.linalg.solve(A,b)
print('Steady State')
print(xstst)
print('Eigenvalues')
print(np.linalg.eigvals(jacobian(f,xstst, A,b)))

# ### PHASE DIAGRAM

# In[13]:

# Plotting Limits
x1lim = [0, 15]  # x1 plotting limits
x2lim = [0,  8]  # x2 plotting limits

# Compute Separatrix
problem.spx(x0=xstst,T=12)

# In[14]:

# Compute Nullclines
x1 = np.linspace(*x1lim, 100)
xnulls = pd.DataFrame({'$\dot{x}_1 =0$': -(A[0,0]*x1 + b[0])/A[0,1],
                       '$\dot{x}_2 =0$': -(A[1,0]*x1 + b[1])/A[1,1]},
                     index = x1)

# In[15]:

problem.phase(x1lim, x2lim,
              xnulls=xnulls,
              title='ODE Phase Diagram',
              animated=2.5 # requires ffmpeg for video, change to 0 for static image
              )

# In[16]:

problem.spx(x0=xstst,T=12)

_build/jupyter_execute/notebooks/ode/03  Initial Value Non-Homogeneous Linear ODE Example.py


# ReLu function

import numpy as np

def relu(z):
    """
    Implements the relu function

    Parameters:
        vector (np.array,list,tuple): A  numpy array of shape (1,n)
        consisting of real values or a similar list,tuple

    Returns:
        relu_vec (np.array): The input numpy array, after applying
        relu.
    """

    # compare two arrays and then return element-wise maxima
    return np.maximum(0,z)


#!/usr/bin/env python
# coding: utf-8

# In[1]:

import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LogisticRegression
from sklearn import datasets

# Write a program using Scikit Learn that utilizes Logistic regression to build a classification
# model using all the four features to predict the class of a plant. Print the confusion matrix,
# accuracy, precision and recall for the model.

# In[2]:

Iris = datasets.load_iris()

# In[3]:

Iris

# In[4]:

print(Iris.data.shape)

# In[5]:

X = Iris.data[:, :4]  # we only take the first two features.
Y = Iris.target

# In[6]:

from sklearn.model_selection import train_test_split

# In[7]:

X_train, X_test, Y_train, Y_test = train_test_split( X, Y, test_size=0.25, random_state=42)

# In[8]:

logmodel = LogisticRegression()

# In[9]:

logmodel.fit(X_train,Y_train)

# In[10]:

Y_pred=logmodel.predict(X_test)
Y_pred

# In[11]:

from sklearn import metrics
print("Accuracy of the model ",metrics.accuracy_score(Y_test,Y_pred))

# In[12]:

from sklearn.metrics import confusion_matrix

# In[13]:

confMat = confusion_matrix(Y_test, Y_pred)
confMat

# In[14]:

labels = Y_test
predictions = Y_pred

cm = confusion_matrix(labels, predictions)
recall = np.diag(cm) / np.sum(cm, axis = 1)
precision = np.diag(cm) / np.sum(cm, axis = 0)

# In[15]:

recall

# In[16]:

precision

# Also, build a classification model in Scikit Learn using Neural Networks using all the features to
# predict the class a plant belongs to. Print the confusion matrix, accuracy, precision and recall for
# the model and compare its performance with the model created using Logistic regression.

# In[17]:

from sklearn.neural_network import MLPClassifier
from sklearn.neural_network import MLPRegressor

# In[18]:

from sklearn.datasets import make_classification

# In[19]:

X, y = make_classification(n_samples=100, random_state=1)
X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y,
                                                    random_state=1)
CLASF = MLPClassifier(random_state=1, max_iter=300).fit(X_train, y_train)
CLASF.predict_proba(X_test[:1])

CLASF.predict(X_test[:5, :])

CLASF.score(X_test, y_test)

# In[20]:

labels = Y_test
predictions = Y_pred

cm = confusion_matrix(labels, predictions)
recall = np.diag(cm) / np.sum(cm, axis = 1)
precision = np.diag(cm) / np.sum(cm, axis = 0)

# In[21]:

cm

# In[22]:

recall

# In[23]:

precision

# In[ ]: