from sympy import symbols, integrate, Rational, lambdify, sqrt, solve
import matplotlib.pyplot as plt
import numpy as np

def plot_fun( fun, name, col ):
	x_vals = np.linspace( g_xlim[0], g_xlim[1], 1000, endpoint=True )
	y_vals = fun( x_vals )
	plt.plot( x_vals, y_vals, label = name, color = col )

# Suppose a company wants to introduce a new machine that will produce a rate of annual savings (in dollars) given by the function Upper S'(x)
# where x is the number of years of operation of the machine, while producing a rate of annual costs (in dollars) given by the function C'(x)
x = symbols( 'x', positive = True )

dS = 212 - x**2
dC = x**2 + Rational( 6, 5 )*x

P = dS - dC

solve( P, x )

# What are the net total savings during the first year of use of the machine?
savings = integrate( P, ( x, 0, 1 ) ).evalf()
round( savings )

#  What are the net total savings over the entire period of use of the machine
savings = integrate( P, ( x, 0, 10 ) ).evalf()
round( savings )

g_xlim = [ 1, 30 ]
g_ylim = [ -5, 15 ]

lam_s = lambdify( x, integrate( dS, x ), np )
plot_fun( lam_s, 'S', 'B' )

lam_c = lambdify( x, integrate( dC, x ), np )
plot_fun( lam_c, 'C', 'Orange' )

lam_p = lambdify( x, integrate( P, x ), np )
plot_fun( lam_p, 'P', 'G' )

plt.legend()
plt.show()


import math
import random
from numba import njit
import numpy as np

@njit
def findPi(num_samples, trials_per_sample):
  samples = np.zeros((num_samples))
  mean = 0.0

  for sample in range(num_samples):
    samples[sample] = integrateCircle(trials_per_sample)

  mean = samples.sum() / samples.shape[0]

  std_dev = getStdDev(mean, samples)

  return mean, std_dev

@njit
def getStdDev(mean, samples):
  variance = 0

  for sample in samples:
    variance += (sample - mean) ** 2

  variance /= samples.shape[0]
  return math.sqrt(variance)

@njit
def integrateCircle(points_placed):
  counter = 0

  for trial in range(points_placed):
    y_pos = random.random()
    x_pos = random.random()

    dist = y_pos ** 2 + x_pos ** 2
    if dist <= 1:
      counter += 1

  return 4.0 * counter / points_placed

res = [0, 0]
for i in range(20):
  res1, res2 = findPi(1000, 50000)
  res[0] += res1 / 20
  res[1] += res2 / 20
print(res)


# Bench mark function 16
# Six-Hump Camel-Back Function
# HW dimension: 2
# Min = -1.031628453489877
# Range [-5,5]
# Reference: https://al-roomi.org/benchmarks/unconstrained/2-dimensions/23-six-hump-camel-back-function

import math
import numpy as np

name = "F16"
l_bound = -5
u_bound = 5
dim = 2
opt = -1.031628453489877

def func(X):
    t1 = 4 * X[0]**2
    t2 = -1 * 2.1 * X[0]**4
    t3 = X[0]**6 / 3
    t4 = np.prod(X)
    t5 = -1 * 4 * X[1]**2
    t6 = 4 * X[1]**4
    result = t1 + t2 + t3 + t4 + t5 + t6
    return result

if __name__ == '__main__':
    X = np.arange(2)  # Dimension must be 2, in [-5 to 5]
    print(X)
    result = func(X)
    print(result)


from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import numpy as np
import helper

def null_vector():
  # MISSING: Create a vector of size 10 and of type np.float32 full of zeros.
  return np.zeros(10, dtype=np.float32)

  return np.array([])

def chess():
  # MISSING: Create a 8x8 matrix and fill it with a checkerboard pattern
  # starting with 1 in the upper left and finishing with 0.
  # The matrix type should be np.int32.
  z = np.zeros((8, 8), dtype=np.int32)
  z[::2, ::2] = 1
  z[1::2, 1::2] = 1
  return z

  return np.array([])

def polar(a):
  # MISSING: "a" is a Nx2 matrix representing cartesian coordinates,
  # convert them to polar coordinates.
  # This function should return a Nx2 matrix where:
  # - the first column is the radius.
  #  -the second column is the angle.
  x = a[:, 0].reshape((-1, 1))
  y = a[:, 1].reshape((-1, 1))
  return np.concatenate([np.sqrt(x ** 2 + y ** 2), np.arctan2(y, x)], axis=1)

  return np.array([])

def cap(a, b):
  # MISSING: Cap all elements of "a" at "b" (i.e., max(a_{i,j}) <= b).
  # BONUS: Make sure to do so without modifying the input arguments.
  c = a.copy()
  c[c > b] = b
  return c

  return np.array([])

def moving_average(a):
  # MISSING: Compute the moving average of the elements of "a" over a
  # window of size 3.
  return np.convolve(a, np.ones(3) / 3., mode='valid')

  return np.array([])

def main():
  helper.check_solution(null_vector, [0] * 10)
  helper.check_solution(chess, [[1, 0, 1, 0, 1, 0, 1, 0],
                                [0, 1, 0, 1, 0, 1, 0, 1],
                                [1, 0, 1, 0, 1, 0, 1, 0],
                                [0, 1, 0, 1, 0, 1, 0, 1],
                                [1, 0, 1, 0, 1, 0, 1, 0],
                                [0, 1, 0, 1, 0, 1, 0, 1],
                                [1, 0, 1, 0, 1, 0, 1, 0],
                                [0, 1, 0, 1, 0, 1, 0, 1]])
  helper.check_solution(polar, [[0.70710678118, np.pi / 4.],
                                [0.70710678118 * 2, np.pi / 4.]],
                        np.array([[.5, .5], [1., 1.]], np.float32),
                        approx=True)
  helper.check_solution(cap, [1, 2, 2], np.array([1, 2, 3]), 2)
  helper.check_solution(cap, [2, 1, 2], np.array([3., 1., 3.]), 2)
  helper.check_solution(moving_average, [2, 3], np.array([1., 2., 3., 4.]))
  helper.check_solution(moving_average, [2], np.array([2., 2., 2.]))

if __name__ == '__main__':
  main()


import numpy as np

def softplus(x):
    """
    log(1 + e^x)

    np.exp を評価してから log をとるため実際の値としては小さくても
    計算機的にはオーバーフローをしてしまうケースがある
    """
    return np.log(1 + np.exp(x))

def softplus2(x):
    """
    max(x, 0) + log(1 + e^{-|x|})

    オーバーフローをしないように同値な式に書き換え
    """
    return max(0, x) + np.log(1 + np.exp(-abs(x)))


from typing import Callable

import numpy as np

def midpoint(
    func: Callable[..., float], a: float, b: float, eps: float = 0.0001, *args, **kwargs
) -> float:

    """
    Aturan titik tengah berfungsi mengoptimasi metode segiempat
    Dengan aturan ini, metode segiempat membagi domain integrasi
    sebanyak n buah dan menjumlahkan seluruh luas segi empat dengan dimensi
    (a + b)/n * f(x), dimana x adalah titik tengah segiempat

    Parameter:
    f   = fungsi input
    a   = batas bawah integrasi
    b   = batas atas integrasi
    eps = error relatif maksimal

    >>> midpoint(lambda x: x**3, 0, 1)
    0.25503446882812497
    >>> midpoint(lambda x: x**10, 0, 1)
    0.09396302982674617
    """
    try:
        n = 100
        x = np.linspace(a, b, n)
        dx = x[1] - x[0]
        L0 = sum([dx * func(i + dx / 2, *args, **kwargs) for i in x])
        err = 1
        while err > eps:
            n += 1
            x = np.linspace(a, b, n)
            dx = x[1] - x[0]
            L1 = sum([dx * func(i + dx / 2, *args, **kwargs) for i in x])
            err = np.abs(L1 - L0) / np.abs(L1)
            L0 = L1
    except Exception:
        raise RuntimeError("Integrasi gagal, pastikan fungsi anda benar!")
    return L1

if __name__ == "__main__":

    def f(x: float) -> float:
        """
        Test Function
        """
        return x ** 3

    print(midpoint(f, 0, 1))

    import doctest

    doctest.testmod()


# based on http://cs231n.github.io/python-numpy-tutorial/

# If you want to use this material in your own trainning please let me know.
#%%

import numpy as np

x = np.array([1, 2])  # Let numpy choose the datatype
print( x.dtype)         # Prints "int64"

x = np.array([1., 2.])  # Let numpy choose the datatype
print( x.dtype)             # Prints "float64"

x = np.array([1, 127], dtype=np.int8)  # Force a particular datatype
print(x.dtype)

#%%
x = np.array([1, 128], dtype=np.int8)  # Force a particular datatype
print(x)

#%% basic math operation
x = np.array([[1,2],[3,4]], dtype=np.float64)
y = np.array([[5,6],[7,8]], dtype=np.float64)

#%% Elementwise sum; both produce the array
# [[ 6.0  8.0]
#  [10.0 12.0]]
print(x + y)
print(np.add(x, y))

#%% Elementwise difference; both produce the array
# [[-4.0 -4.0]
#  [-4.0 -4.0]]
print(x - y)

print(np.subtract(x, y))

#%% Elementwise product; both produce the array
# [[ 5.0 12.0]
#  [21.0 32.0]]
print(x * y)
print(np.multiply(x, y))

#%% Elementwise division; both produce the array
# [[ 0.2         0.33333333]
#  [ 0.42857143  0.5       ]]
print(x / y)
print(np.divide(x, y))

#%%
# list of math functions https://numpy.org/doc/stable/reference/routines.math.html

#%% Elementwise square root; produces the array
# [[ 1.          1.41421356]
#  [ 1.73205081  2.        ]]
print( np.sqrt(x))

#%% vector matrix operation
x = np.array([[1,2],[3,4]])
y = np.array([[5,6],[7,8]])

v = np.array([9,10])
w = np.array([11, 12])

#%% Inner product of vectors; both produce 219
print( v.dot(w))
print( np.dot(v, w))

# Matrix / vector product; both produce the rank 1 array [29 67]
print(x.dot(v))
print(np.dot(x, v))

# Matrix / matrix product; both produce the rank 2 array
# [[19 22]
#  [43 50]]
print(x.dot(y))
print(np.dot(x, y))

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

print(x)
print(np.sum(x))  # Compute sum of all elements; prints "10"
print(np.sum(x, axis=0))# Compute sum of each column; prints "[4 6]"
print(np.sum(x, axis=1))  # Compute sum of each row; prints "[3 7]"

#%%
print(np.mean(x))  # Compute mean of all elements;
print(np.mean(x, axis=0))# Compute mean of each column;
print(np.mean(x, axis=1))  # Compute mean of each row;

#%%
print(np.std(x))          # Compute standard derivation of all elements;
print(np.std(x, axis=0))  # Compute standard derivation of each column;
print(np.std(x, axis=1))  # Compute standard derivation of each row;

#%%
x = np.array([[1,2], [3,4]])
print(x)    # Prints "[[1 2]
           #          [3 4]]"
print(x.T)  # Prints "[[1 3]
           #          [2 4]]"

#%% Note that taking the transpose of a rank 1 array does nothing:
v = np.array([1,2,3])
print(v)  # Prints "[1 2 3]"
print(v.T)  # Prints "[1 2 3]"

# generate linear map from (-pi/2, pi/2)
x = np.linspace(-np.pi/2,np.pi/2,10)

# calculate sine and cosine in one step, for whole array
print(np.sin(x))

print(np.cos(x))

# [-5, ... , 5]
x = np.arange(-5,5)

#%% calcultae e^(-5), .... , e^5
print(np.exp(x))

#%% x^2, compute x to power of 2
print(np.power(x,2))

# using python operators compute each element of matrix x to power of 2
print(x**2)

# calculate 2^-5 ... 2^5, !!! error, integer not allowed negative exponent
print(np.power(2,x))

# now everything works as expected :)
x = np.arange(-5,5, dtype=np.float)

# natural logarithm, look at minus values!!
print(np.log(x))

xx = np.power(2,x)
print(xx)

# logarithm base 2
print(np.log2(xx))


"""Solving  a System of ODEs"""

"""Euler's Method""" """Approximation of functions/differential equations""" """NOT ROOT FINDING"""
# importing modules
import numpy as np
import matplotlib.pyplot as plt
import math
# ------------------------------------------------------
# functions that returns dy/dx
# i.e. the equation we want to solve: dy_j/dx = f_j(x,y_j)
# (j=[1,2] in this case)
def model(x,y_1,y_2):
    f_1 = -0.5 * y_1
    f_2 = 4.0 - 0.3 * y_2 - 0.1 * y_1
    return [f_1 , f_2]
# ------------------------------------------------------
# ------------------------------------------------------
# initial conditions
x0 = 0
y0_1 = 4
y0_2 = 6
# total solution interval
x_final = 2
# step size
h = 0.00001
# ------------------------------------------------------
# ------------------------------------------------------
# Euler method
# number of steps
n_step = math.ceil(x_final/h)
# Definition of arrays to store the solution
y_1_eul = np.zeros(n_step+1)
y_2_eul = np.zeros(n_step+1)
x_eul = np.zeros(n_step+1)
# Initialize first element of solution arrays
# with initial condition
y_1_eul[0] = y0_1
y_2_eul[0] = y0_2
x_eul[0] = x0
# Populate the x array
for i in range(n_step):
    x_eul[i+1] = x_eul[i] + h
# Apply Euler method n_step times
for i in range(n_step):
    # compute the slope using the differential equation
    [slope_1 , slope_2] = model(x_eul[i],y_1_eul[i],y_2_eul[i])
    # use the Euler method
    y_1_eul[i+1] = y_1_eul[i] + h * slope_1
    y_2_eul[i+1] = y_2_eul[i] + h * slope_2
print(f'Values of y_1: {y_1_eul[i]} and y_2: {y_2_eul[i]}')

"""Solve IVP METHOD""" """INTEGRATION"""
# importing modules
import numpy as np
import matplotlib.pyplot as plt
import math
from scipy.integrate import solve_ivp
# ------------------------------------------------------
# functions that returns dy/dx
# i.e. the equation we want to solve:
# dy_j/dx = f_j(x,y_j) (j=[1,2] in this case)
def model(x,y):
    y_1 = y[0]
    y_2 = y[1]
    f_1 = -0.5 * y_1
    f_2 = 4.0 - 0.3 * y_2 - 0.1 * y_1
    return [f_1 , f_2]
# ------------------------------------------------------
# ------------------------------------------------------
# initial conditions
x0 = 0
y0_1 = 4
y0_2 = 6
# total solution interval
x_final = 2
# step size
# not needed here. The solver solve_ivp
# will take care of finding the appropriate step
# -------------------------------------------------
# ------------------------------------------------------
# Apply solve_ivp method
y = solve_ivp(model, [0 , x_final] ,[y0_1 , y0_2])
# ------------------------------------------------------
# ------------------------------------------------------
# plot results
plt.plot(y.t,y.y[0,:] , 'b.-',y.t,y.y[1,:] , 'r-')
plt.xlabel('x')
plt.ylabel('y_1(x), y_2(x)')
plt.show()
# ------------------------------------------------------
# ------------------------------------------------------
# print results in a text file (for later use if needed)
file_name= 'output.dat'
f_io = open(file_name,'w')
n_step = len(y.t)
for i in range(n_step):
    s1 = str(i)
    s2 = str(y.t[i])
    s3 = str(y.y[0,i])
    s4 = str(y.y[1,i])
    s_tot = s1 + ' ' + s2 + ' ' + s3 + ' ' + s4
    f_io.write(s_tot + '\n')
f_io.close()
# ------------------------------------------------------

"""Implicit Euler Method""" """MAGIC BULLET FOR STIFF SYSTEMS"""

# importing modules
import numpy as np
import matplotlib.pyplot as plt
import math
# ------------------------------------------------------
# inputs
# functions that returns dy/dx
# i.e. the equation we want to solve: dy/dx = - y
def model2(y,x):
    dydx = -1000.0*y + 3000.0 - 2000.0*math.exp(-x)
    return dydx
# initial conditions
x0 = 0
y0 = 0
# total solution interval
x_final = 0.3
# step size
h = 0.05
# ------------------------------------------------------
# Secant method (a very compact version)
def secant_2(f, a, b, iterations):
    for i in range(iterations):
        c = a - f(a)*(b - a)/(f(b) - f(a))
        if abs(f(c)) < 1e-13:
            return c
        a = b
        b = c
    return c
# ------------------------------------------------------
# Euler implicit method
# number of steps
n_step = math.ceil(x_final/h)
# Definition of arrays to store the solution
y_eul = np.zeros(n_step+1)
x_eul = np.zeros(n_step+1)
# Initialize first element of solution arrays
# with initial condition
y_eul[0] = y0
x_eul[0] = x0
# Populate the x array
for i in range(n_step):
    x_eul[i+1] = x_eul[i] + h
# Apply implicit Euler method n_step times
for i in range(n_step):
    F = lambda y_i_plus_1: y_eul[i] + model2(y_i_plus_1,x_eul[i+1])*h - y_i_plus_1
    y_eul[i+1] = secant_2(F, y_eul[i],1.1*y_eul[i]+10**-3,10)
    print(y_eul[i+1])


#!python
# -*- coding: utf-8 -*-#
"""
:Title: Multivariate Linear Regression.

@author: Bhishan Poudel

@date: Sep 22, 2017

@email: bhishanpdl@gmail.com

The cost function is given by

.. math::

  J(w) = \\frac{1}{2N} \sum_{n=1}^N (h(x_n,w) - t_n)^2

Minimizing the cost function w.r.t. w gives the solution:

.. math::

  w = np.linalg.lstsq(X1,t)[0]
"""
# Imports
import argparse
import sys
import numpy as np
from matplotlib import pyplot as plt
import numpy.polynomial.polynomial as poly
from numpy.core.umath_tests import inner1d
from numpy.linalg import norm,lstsq,inv

# for univariate multivariate comparison
from univariate import univariate_reg

# checking
#

# Read data matrix X and labels t from text file.
def read_data(infile):
    """Read the datafile.

    Args:
      infile (str): path to datafile

    """
    # data = np.loadtxt(infile)
    data = np.genfromtxt(infile, delimiter=None, dtype=float)
    X = data[:, :-1]
    t = data[:, [-1]]
    return X, t

#----------------------------------------------------------------------#
#  function: train                                                     #
#----------------------------------------------------------------------#
# Here no. of features M = 3 (floor, bedrooms, age)
# Implement normal equations to compute w = [w0, w1, ..., w_M].
def train(X1, t):
    """Train the data and return the weights w.

    Args:

      X1 (array): Design matrix of size (m+1, n). I.e. There are
        m features and one bias column in the matrix X1.

      t (column): target column vector

    .. note::

       Here the design matrix X1 should have one extra bias term.

    .. warning::

       The operator @ requires python >= 3.5

    """
    # Method 1
    w = np.linalg.inv(X1.T.dot(X1)) .dot(X1.T) .dot(t)
    w = np.array(w).reshape(1, len(w)) # make 1d row array

    # Method 2
    # w = (inv(X1.T @ X1)) @ X1.T @ t
    # w = np.array(w).reshape(1, len(w)) # make 1d row array

    # Method 3
    # w = np.linalg.lstsq(X1,t)[0]
    # w = np.array(w).reshape(1, len(w)) # make 1d row array

    return w

# Compute RMSE on dataset (X, t).
def compute_rmse(X, t, w):
    """Compute the RMSE.

    RMSE is the root mean square error.

    .. math:: RMSE = \sqrt{\sum_{i=1}^{n}  \\frac{(h - t)^2}{n} }

    h is the hypothesis.

    :math:`h = X w^T`

    To find the norm of the residual matrix h-t we may use
    the code::

      # inner1d is the fastest subroutine.
      from numpy.core.umath_tests import inner1d
      np.sqrt(inner1d(h-t,h-t))

      # We can also use another method:
      ht_norm = np.linalg.norm(h - t)

    """

    # Method 1
    h = np.dot(X, w.T) # h = X @ w.T
    rmse = np.sqrt(((h - t) ** 2).mean())

    # Method 2
    # h = np.dot(X, w.T)
    # ht_norm = np.sqrt(inner1d(h-t,h-t))
    # rmse = ht_norm / np.sqrt(len(X))
    # rmse = rmse[0]

    # Method 3
    # norm is square root of sum of squares
    # rmse is norm/ sqrt(n)
    #
    # h = np.dot(X, w.T)
    # ht_norm = np.linalg.norm(h - t)
    # rmse = ht_norm / np.sqrt(len(X))

    # Checking
    # print("t.shape = ", t.shape)
    # print("w.shape = ", w.shape)
    # print("h.shape = ", h.shape)
    # print("X.shape = ", X.shape)
    # print("len(X1) = ", len(X))

    # Checking
    # rmse = 0.0
    # try:
    #     from sklearn.metrics import mean_squared_error
    #     rmse = mean_squared_error(h, t)**0.5
    #     rmse = np.sqrt(np.square(h - t).mean())
    # except:
    #     print('Error: The library sklearn not installed!')

    # Return RMSE
    return rmse

# Compute objective function (cost) on dataset (X, t).
def compute_cost(X, t, w):
    """Compute the cost function.

    .. math:: J = \\frac{1}{2n} \sum_{i=1}^{n}  \\frac{(h - t)^2}{n}

    """

    # Compute cost
    # N = float(len(t))
    # h = np.dot(X, w.T)   # h = X @ w.T
    # J = np.sum((h - t) ** 2) /2 / N

    # One liner
    J = np.sum((X @ w.T - t) ** 2) /2 / float(len(t))

    return J

def check_results(y_train, x1_train):
    """Multivariate Regression with statsmodels.api

    Args:
      y_train (float): target column vector of floats.
      x1_train (array): features+1 dimensional numpy array

    This fits the multivariate linear regression in four lines::

        import statsmodels.api as sm
        model = sm.OLS(y_train, x1_train)
        result = model.fit()
        print (result.summary())

    """
    try:
        import statsmodels.api as sm
        model = sm.OLS(y_train, x1_train)
        result = model.fit()
        print (result.summary())

    except:
        print('Error: statsmodels libray not found!')

##=======================================================================
## Main Program
##=======================================================================
def main():
    parser = argparse.ArgumentParser('Multivariate Exercise.')
    parser.add_argument('-i', '--input_data_dir',
                        type=str,
                        default='../data/multivariate',
                        help='Directory for the multivariate houses dataset.')
    FLAGS, unparsed = parser.parse_known_args()

    # Read the training and test data.
    Xtrain, ttrain = read_data(FLAGS.input_data_dir + "/train.txt")
    Xtest, ttest = read_data(FLAGS.input_data_dir + "/test.txt")

    #  Append ones to the first column
    X1train  = np.append(np.ones_like(ttrain), Xtrain, axis= 1)
    X1test  = np.append(np.ones_like(ttest), Xtest, axis= 1)

    # debug
    # print(" First column X1train[:, [0]] = \n{}".format(X1train[:, [0]]))
    # print(" First row X1train[0] = \n{}".format(X1train[0]))

    # Train model on training examples.
    w = train(X1train, ttrain)

    # Print model parameters.
    print("#"*50)
    print("Multivariate Regression")
    print('Params Mulitvariate: ', w[0], '\n')

    # Print cost and RMSE on training data.
    # train
    E_rms_train_multi = compute_rmse(X1train, ttrain, w)
    J_train_multi = compute_cost(X1train, ttrain, w)

    # test
    E_rms_test_multi = compute_rmse(X1test, ttest, w)
    J_test_multi = compute_cost(X1test, ttest,w)

    print('E_rms_train Multivariate: %0.2e' % E_rms_train_multi)
    print('J_train Multivariate: %0.2e' % J_train_multi)

    # Print cost and RMSE on test data.
    print("\n")
    print('E_rms_test Multivariate: %0.2e' % E_rms_test_multi)
    print('J_test Multivariate: %0.2e' % J_test_multi)

    #===========================================================
    print("\n")
    print("="*50)
    print("Comparison of Univariate and Multivariate")
    fh_train_uni = '../data/univariate/train.txt'
    fh_test_uni = '../data/univariate/test.txt'

    E_rms_train_uni, J_train_uni, E_rms_test_uni, J_test_uni = univariate_reg(fh_train_uni, fh_test_uni)

    print('Univariate             Multivariate')
    print("E_train = {:.4e}     {:.4e}".format(E_rms_train_uni, E_rms_train_multi))
    print("E_test  = {:.4e}     {:.4e}".format(E_rms_test_uni , E_rms_test_multi))
    print("J_train = {:.4e}     {:.4e}".format(J_train_uni    , J_train_multi))
    print("J_test  = {:.4e}     {:.4e}".format(J_test_uni     , J_test_multi))
    print("-"*50)
    print('Multivariate Params are given below:')
    print([ "{:.2e}".format(x) for x in list(w[0])])
    print("#"*20, "The End", "#"*20)
    print("\n")

    # Check result with statsmodels
    # check_results(ttrain, X1train)

if __name__ == "__main__":
    # Run main function
    main()

import numpy,from numpy,import statsmodels


import numpy as np
import matplotlib.pyplot as plt

def condition_points(points):
    """ Conditioning: Normalization of coordinates for numeric stability
    by substracting the mean and dividing by half of the component-wise
    maximum absolute value.
    Args:
        points: (l, 3) numpy array containing unnormalized homogeneous coordinates.

    Returns:
        ps: (l, 3) numpy array containing normalized points in homogeneous coordinates.
        T: (3, 3) numpy array, transformation matrix for conditioning
    """
    t = np.mean(points, axis=0)[:-1]
    s = 0.5 * np.max(np.abs(points), axis=0)[:-1]
    T = np.eye(3)
    T[0:2, 2] = -t
    T[0:2, 0:3] = T[0:2, 0:3] / np.expand_dims(s, axis=1)
    ps = points @ T.T
    return ps, T

def enforce_rank2(A):
    """ Enforces rank 2 to a given 3 x 3 matrix by setting the smallest
    eigenvalue to zero.
    Args:
        A: (3, 3) numpy array, input matrix

    Returns:
        A_hat: (3, 3) numpy array, matrix with rank at most 2
    """

    #
    # You code here
    #
    u, s, vh = np.linalg.svd(A, full_matrices=True)
    s_rank2 = s
    s_rank2[-1] = 0
    A_hat = u @ np.diag(s_rank2) @ vh
    return A_hat

def compute_fundamental(p1, p2):
    """ Computes the fundamental matrix from conditioned coordinates.
    Args:
        p1: (n, 3) numpy array containing the conditioned coordinates in the left image
        p2: (n, 3) numpy array containing the conditioned coordines in the right image

    Returns:
        F: (3, 3) numpy array, fundamental matrix
    """

    #
    # You code here
    #
    A_list = []
    for i, p in enumerate(p1):  # [0:8,:] pick 8 ponts
        temp = np.array(
            [p[0] * p2[i][0], p[1] * p2[i][0], p2[i][0], p[0] * p2[i][1], p[1] * p2[i][1], p2[i][1], p[0], p[1], 1])
        A_list.append(temp)
    A = np.asarray(A_list)
    u, s, vh = np.linalg.svd(A, full_matrices=True)
    V = vh.T
    F = np.reshape(V[:, -1], (3, 3))  # check!
    # F/=F[2,2]
    return F

def eight_point(p1, p2):
    """ Computes the fundamental matrix from unconditioned coordinates.
    Conditions coordinates first.
    Args:
        p1: (n, 3) numpy array containing the unconditioned homogeneous coordinates in the left image
        p2: (n, 3) numpy array containing the unconditioned homogeneous coordinates in the right image

    Returns:
        F: (3, 3) numpy array, fundamental matrix with respect to the unconditioned coordinates
    """

    #
    # You code here
    #
    ps1, T1 = condition_points(p1)
    ps2, T2 = condition_points(p2)
    F_rank3 = compute_fundamental(ps1, ps2)
    F_hat = enforce_rank2(F_rank3)
    F = T2.T @ F_hat @ T1
    return F

def cart2hom(p_c):
    p_h = np.concatenate([p_c, np.ones((p_c.shape[0], 1))], axis=1)
    return p_h

def draw_epipolars(F, p1, img):
    """ Computes the coordinates of the n epipolar lines (X1, Y1) on the left image border and (X2, Y2)
    on the right image border.
    Args:
        F: (3, 3) numpy array, fundamental matrix
        p1: (n, 2) numpy array, cartesian coordinates of the point correspondences in the image
        img: (H, W, 3) numpy array, image data

    Returns:
        X1, X2, Y1, Y2: (n, ) numpy arrays containing the coordinates of the n epipolar lines
            at the image borders
    """

    #
    # You code here
    #
    p1_homo = cart2hom(p1)
    normals = (F @ p1_homo.T).T  # normals: (n,3)
    # only check pixel coordinates on borders
    X1 = []
    X2 = []
    Y1 = []
    Y2 = []  # 2 intersected points on borders
    img_H = img.shape[0]
    img_W = img.shape[1]

    # construct coordinates of pixels on borders
    p_coordinates_borders = []
    for row in range(0, img_H):
        for col in range(0, img_W):
            if (0 < row < img_H - 1 and 0 < col < img_W - 1):
                continue
            p_coordinates_borders.append(np.array([col, row, 1]))  # (x:width, y:height, 1)homogenous
    A_p_coordinates_borders = np.asarray(p_coordinates_borders)

    # dot product of pixel coordinates and normal vector
    dot_product_normals = []  # => (n, number of pixels)
    for normal in normals:  # n iterations
        dot_product_normal = []  # => (number of pixels, )
        for p in p_coordinates_borders:
            normal_vector = normal.flatten()
            dot_product_normal.append(np.dot(normal_vector, p))
        dot_product_normals.append(np.asarray(dot_product_normal))

    A_dot_product_normals = np.asarray(dot_product_normals)
    ind = np.argsort(np.abs(A_dot_product_normals),
                     axis=1)  # (n, number of pixels), sorts along second axis (--), dot_product can be negativ
    # min=np.min(np.abs(A_dot_product_normals), axis=1)
    # print(np.sort(np.abs(A_dot_product_normals[0])))
    # find coordinates of 2 pixels with smallest dot product
    for n, dot_product_ind in enumerate(
            ind):  # row, dot_product_ind[[0,1]] are the indices of the 2 2 pixels with smallest dot product
        ind1 = dot_product_ind[0]
        coor1 = p_coordinates_borders[ind1]
        X1.append(coor1[0])  # W
        Y1.append(coor1[1])  # H
        # print(A_dot_product_normals[n][ind1])

        ind2 = dot_product_ind[1]
        coor2 = p_coordinates_borders[ind2]
        X2.append(coor2[0])
        Y2.append(coor2[1])
        # print(A_dot_product_normals[n][ind2])

    A_X1 = np.asarray(X1)
    A_X2 = np.asarray(X2)
    A_Y1 = np.asarray(Y1)
    A_Y2 = np.asarray(Y2)
    return A_X1, A_X2, A_Y1, A_Y2

def compute_residuals(p1, p2, F):
    """
    Computes the maximum and average absolute residual value of the epipolar constraint equation.
    Args:
        p1: (n, 3) numpy array containing the homogeneous correspondence coordinates from image 1
        p2: (n, 3) numpy array containing the homogeneous correspondence coordinates from image 2
        F:  (3, 3) numpy array, fundamental matrix

    Returns:
        max_residual: maximum absolute residual value
        avg_residual: average absolute residual value
    """

    #
    # You code here
    #
    residual = p1 @ F @ p2.T
    residual_abs = np.abs(residual)
    max_residual = np.max(residual_abs)
    avg_residual = np.mean(residual_abs)
    return max_residual, avg_residual

def compute_epipoles(F):
    """ Computes the cartesian coordinates of the epipoles e1 and e2 in image 1 and 2 respectively.
    Args:
        F: (3, 3) numpy array, fundamental matrix

    Returns:
        e1: (2, ) numpy array, cartesian coordinates of the epipole in image 1
        e2: (2, ) numpy array, cartesian coordinates of the epipole in image 2
    """

    #
    # You code here
    #

    u, s, vh1 = np.linalg.svd(F.T)
    e1 = vh1.T[:, -1]
    e1 /= e1[2]

    u, s, vh2 = np.linalg.svd(F)
    e2 = vh2.T[:, -1]
    e2 /= e2[2]
    return e1[0:2], e2[0:2]


import numpy as np
import scipy.linalg as splg
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import matplotlib.figure as fg

def heatEquationMatrix(n):
    ''' Returns a tridiagonal n^2*n^2 matrix A to solve the heat equation
    in a discrete way by solving the linear system Ax = b, where b is a n^2
    vector such as b[n*x+y] is the heat flux density in the point (x,y)
    and h is the distance on both axis between 2 consecutive points'''
    N = n*n

    A = np.diag([1]*(N-n), -n) + np.diag([1]*(N-n), n)
    sub = -4*np.eye(n) + np.diag([1]*(n-1), 1) + np.diag([1]*(n-1), -1)
    for i in range(0, n):
        A[i*n:(i+1)*n,i*n:(i+1)*n] = sub[:,:]
    return A

def matToVect(M):
    ''' M shoud be a square matrix of size nxn
    Returns a vector containing the values in M, readfrom the left hand column
    to the right hand column, from top to bottom, and stop from top to bottom'''
    n = M.shape[0]
    return M.transpose().reshape((n*n,))

def vectToMat(v):
    ''' v shoud be a vector of length nxn
    Returns a matrix containing the values in v, read from top to bottom and then
    stored from the left hand column to the right hand column, from top to bottom'''
    n = np.sqrt(v.shape[0])
    return v.reshape((n,n))

def solveHeatEquation(heatFlux, h, conductivity):
    n = heatFlux.shape[0]
    heatFlux = matToVect(heatFlux)*h*h/conductivity
    M = heatEquationMatrix(n)
    T = np.linalg.cholesky(-M)
    y = splg.solve_triangular(T, heatFlux, lower=True, check_finite=False)
    x = splg.solve_triangular(-T.transpose(), y, check_finite=False)
    return vectToMat(x)

def printHeatSolution(sol):
    plt.imshow(sol.transpose(), interpolation='bilinear', cmap=cm.jet_r)
    plt.colorbar()
    plt.show()

# size = 50
# h = 0.01
# airConductivity = 0.025
# heatFlux = np.zeros((size,size))
# # ext[size/2][size/2] = 200
# heatFlux[10][10] = 100
# heatFlux[10][30] = 150
# heatFlux[30][10] = 200
# heatFlux[30][30] = 250

# printHeatSolution(solveHeatEquation(heatFlux, h, airConductivity))


import numpy as np

def forward_substitution(L, b):
    y = np.full_like(b, 0)
    for k in range(len(b)):
        y[k] = b[k]
        for i in range(k):
            y[k] = y[k] - (L[k, i] * y[i])
        y[k] = y[k] / L[k, k]
    return y

def backward_substitution(U, y):
    x = np.full_like(y, 0)
    for k in range(len(x), 0, -1):
        x[k - 1] = (y[k - 1] - np.dot(U[k - 1, k:], x[k:])) / U[k - 1, k - 1]
    return x

def cholesky_decomposition(A):
    n = len(A)
    L = np.ones((n, n)) * 0.0
    for i in range(n):
        for j in range(i + 1):
            if i == j:
                sum = 0
                for k in range(i):
                    sum = sum + L[i][k] ** 2
                L[i][i] = (A[i][i] - sum) ** 0.5
            else:
                sum = 0
                for k in range(j):
                    sum = sum + L[i][k] * L[j][k]
                L[i][j] = (A[i][j] - sum) / L[j][j]
    U = L.transpose()

    return L, U

def solution(A, b):

    y = forward_substitution(L, b)
    x = backward_substitution(U, y)

    return x

A = np.array([[1, 1, 1], [1, 2, 2], [1, 2, 3]])
print('A:', A)
b = np.array([1, 1.5, 3])
print('b:', b)
L, U = cholesky_decomposition(A)
print('L:', L)
print('U:', U)

print('***SOLUTION***')
x = solution(A, b)
print('x:', x)


import sys
sys.path.append("../")
from sir import *
from sir.SIR_continuous_reinfected import *
import pandas as pd
import matplotlib.pyplot as plt
import scipy.optimize as opt
t=pd.read_csv("../data/case_daily_trends__united_states.csv",header=2).iloc[:,2] # read in daily case in US
t=pd.read_csv("../data/case_total_and_rate_per_100000__united_states.csv",header=2).iloc[:,1] # read in total case in US
total_case=np.array(t)
total_case[:10]

totalpopulation=328200000 # total population in us
S=totalpopulation-total_case
S=S/totalpopulation # in percentage
IandR=total_case/totalpopulation
time=[*range(len(total_case), 0, -1)]
plt.plot(time,S,label="S")
plt.plot(time,IandR,label="I+R")
plt.legend()
plt.xlabel("number of days")
plt.ylabel("probabillity")
plt.show()

b=0.1
k=0.1
time=319
ii=0.01
r=0
q=1

sol1=SIR_continuous_reinfected(b,k,time,ii,r)
plt.plot(sol1.t, sol1.y[0], c='b',label='s')    # generate the plot
plt.plot(sol1.t, (sol1.y[1]+sol1.y[2]), c='g',label='r+i')
#plt.plot(sol1.t, sol1.y[2]*1000, c='r',label='i')
plt.show()

def loss(b,k,r):
    """
    loss function with parameter b, k,r
    """
    ii=0.01
    time=len(S)
    q=1
    sol1=SIR_continuous_reinfected(b,k,time,ii,r)
    return np.linalg.norm(sol1.y[0]-S)+np.linalg.norm((sol1.y[1]+sol1.y[2])-IandR)

def loss2(x):
    """
    loss function with vector x that contains b,k,r
    """
    b=x[0]
    k=x[1]
    r=x[2]
    ii=0.01
    time=len(S)
    q=1
    sol1=SIR_continuous_reinfected(b,k,time,ii,r)
    return np.linalg.norm(sol1.y[0]-S)+np.linalg.norm((sol1.y[1]+sol1.y[2])-IandR)

def loss3(x):
    """
    loss function for r
    """
    b=0.0001
    k=0.074
    ii=0.01
    time=len(S)
    q=1
    sol1=SIR_continuous_reinfected(b,k,time,ii,x)
    return np.linalg.norm(sol1.y[0]-S)+np.linalg.norm((sol1.y[1]+sol1.y[2])-IandR)

sol = opt.minimize(loss2, np.array([-9.66889007e-06, -9.85879953e-01,  9.77224552e-01]))
sol

losslist=[]
rlist=[]
n=1000
for i in range(n):
    r=i/n
    losslist.append(loss3(r))
    rlist.append(r)
plt.plot(rlist,losslist)
plt.xlabel('r')
plt.ylabel('loss')
plt.title('The relationship of reinfection rate and loss function')
plt.savefig('rvsloss')

b=0.0001
k=0.074
time=319
ii=0.01
r=0.01
q=1
times=[*range(len(total_case), 0, -1)]
sol1=SIR_continuous_reinfected(b,k,time,ii,r)
plt.plot(sol1.t, sol1.y[0], c='b',label='S(simulation)')    # generate the plot
plt.plot(sol1.t, (sol1.y[1]+sol1.y[2]), c='g',label='R+I(Simulation)')
plt.plot(times,S,label="S(data)")
plt.plot(times,IandR,label="I+R(data)")
plt.legend()
plt.title("COVID 19: SIR model vs data")
plt.savefig('modelvsdata')


#!/usr/bin/env python
# coding: utf-8
## Monte Carlo - Forecasting StockType Prices - Part I
# *Suggested Answers follow (usually there are multiple ways to solve a problem in Python).*
# Download the data for Microsoft (�MSFT�) from Yahoo Finance for the period �2000-1-1� until today.
# Download the data for Microsoft (�MSFT�) from IEX for the period �2015-1-1� until today.
# Forecasting Future StockType Prices � continued:
import numpy as np
import pandas as pd
from pandas_datareader import data as wb
import matplotlib.pyplot as plt
from scipy.stats import norm

# get_ipython().run_line_magic('matplotlib', 'inline')
# In[2]:
# ticker = 'PG'
# ticker = 'MSFT'
# data = pd.DataFrame()
# data[ticker] = wb.DataReader(ticker, data_source='yahoo', start='2007-1-1')['Adj Close']
# data[ticker] = wb.DataReader(ticker, data_source='iex', start='2015-1-1')['close']
data = pd.read_csv('Section-17_PG_2007_2017.csv', index_col='Date')
data = pd.read_csv('Section-17_MSFT_2000.csv', index_col='Date')
data.plot(figsize=(10, 6));
# Use the .pct_change() method to obtain the log returns of Microsoft for the designated period.
log_returns = np.log(1 + data.pct_change())
log_returns.tail()
log_returns.plot(figsize=(10, 6))
# Assign the mean value of the log returns to a variable, called �U�, and their variance to a variable, called �var�.
u = log_returns.mean()
u
# In[7]:
var = log_returns.var()
var
# Calculate the drift, using the following formula:
# $$
# drift = u - \frac{1}{2} \cdot var
# $$
drift = u - (0.5 * var)
drift
# Store the standard deviation of the log returns in a variable, called �stdev�.
stdev = log_returns.std()
stdev
# ******
# Use �.values� to transform the *drift* and the *stdev* objects into arrays.
type(drift)
drift.values
# In[4]:
type(stdev)
# In[12]:
np.array(drift)
drift.values
# In[14]:
stdev.values
# Forecast future stock prices for every trading day a year ahead. So, assign 250 to �t_intervals�.
# Let�s examine 10 possible outcomes. Bind �iterations� to the value of 10.
t_intervals = 250
t_intervals = 1000
iterations = 10
# Use the formula we have provided and calculate daily returns.
# $$
# r = drift + stdev \cdot z
# $$
# $$
# daily\_returns = exp({drift} + {stdev} * z),
# $$
# $$
# where\  z = norm.ppf(np.random.rand(t\_intervals, iterations)
# $$
# $$
# daily\_returns = e^{r}
# $$
daily_returns = np.exp(drift.values + stdev.values * norm.ppf(np.random.rand(t_intervals, iterations)))
daily_returns
# $$
# S_t = S_0 \mathbin{\cdot} daily\_return_t
# $$
# $$
# S_{t+1} = S_t \mathbin{\cdot} daily\_return_{t+1}
# $$
# $$...$$
# $$
# S_{t+999} = S_{t+998} \mathbin{\cdot} daily\_return_{t+999}
# $$
# ***
# Create a variable S0 equal to the last adjusted closing price of Microsoft. Use the �iloc� method.
S0 = data.iloc[-1]
S0
# Create a variable price_list with the same dimension as the daily_returns matrix.
price_list = np.zeros_like(daily_returns)
price_list
price_list[0]
# Set the values on the first row of the price_list array equal to S0.
price_list[0] = S0
price_list
# Create a loop in the range (1, t_intervals) that reassigns to the price in time t the product of the price in day (t-1) with the value of the daily returns in t.
for t in range(1, t_intervals):
    price_list[t] = price_list[t - 1] * daily_returns[t]
price_list
# Finally, plot the obtained price list data.
plt.figure(figsize=(10, 6))
plt.plot(price_list);


import numpy as np

def power_eig(A, b0=None, max_steps=50, eps=1e-10):
    # set initial vector
    if b0 is None:
        b = np.random.rand(A.shape[0])
    else:
        b = b0
    # apply power method until we took too many steps or we converged
    for i in range(max_steps):
        new_b = A.dot(b)
        new_b /= np.linalg.norm(new_b)
        if np.linalg.norm(b - new_b) < eps:
            b = new_b # eigen vector
            break
        b = new_b
    else:
        raise ValueError("failed to converge")
    # compute eigen value
    # Ab = lb
    lb = A.dot(b)
    b_has_zero = b != 0
    eigen_val = np.mean(b[b_has_zero]/b[b_has_zero])
    return eigen_val, b

A = np.array([[0, 0, 1],
              [0, 1, 0],
              [1, 0, 0]], dtype="float")

val, vec = power_eig(A, b0=np.array([1,1,1]), eps=1e-5)

print("matrix:\n", A)
print("has eigen value", val, "with eigenvector", vec)


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

@author: Sushant

"""

import numpy as np
import scipy

######################################## Least Square Linear Regression ####################################
def LinearRegression(data,labels):
    numdata = int( np.size(data,0) )
    b1 = np.hstack(( data,np.ones((numdata,1)) ) )
    XXT = np.matmul(b1.T,b1)
    invXXT = np.linalg.pinv(XXT)
    b2 = np.matmul(b1.T,labels)
    w = np.matmul(invXXT,b2)
    return w

###################################### Ridges Regression ###################################################

def RidgeRegression(data,labels,lambda):
    numdata = int( np.size(data,0) )
    b1 = np.hstack(( data,np.ones((numdata,1)) ) )
    XXT = np.matmul(b1.T,b1) + lambda*np.identity(np.size(b1,1))
    b2 = np.matmul(b1.T,labels)
    #solved using Cholesky decompostion Ax = b
    b3 = scipy.linalg.cho_factor( XXT )
    w = scipy.linalg.cho_solve(b3,b2)
    return w

###################################### Predict values and Least Square Error###############################
def PredictLabels(testdata,w):
    numdata = int( np.size(testdata,0) )
    b3 = np.hstack( ( testdata,np.ones((numdata,1)) ) )
    pred = np.matmul(b3,w)
    return pred

def ltsqerror(prelabels,actlabels):
    return np.sum((prelabels-actlabels)**2)/int(np.size(prelabels,0))

####################################### Kernel Ridges Regression ########################################

def linear(x1,x2,p = None):
    return np.dot(x1,x2)

def polynomial(x1,x2,d):
    return ( 1+np.dot(x1,x2) )**d

def rbf(x1,x2,l):
    return  np.exp( -np.divide(np.dot(x1-x2,x1-x2), 2*(l**2 ) )    )

def KernelRidgeRegression(data,labels,lamda,kernel,p):
    numdata =  int( np.size(data,0) )
    traindata = np.asarray(data)
    #=========Kernel matrix======================
    K =  np.zeros((numdata,numdata))
    for i in range(0,numdata):
        for j in range(0,numdata):
            K[i,j] = kernel(traindata[i,:],traindata[j,:],p)
    #solved using Cholesky decompostion Ax = b
    b1 = scipy.linalg.cho_factor( K + lamda*np.identity(numdata) )
    alphas = scipy.linalg.cho_solve(b1,labels)
    return alphas

def KernelRidgesRegression_predict(traindata1,alphas,testdata1,kernel,p):
    numtraindata =  int( np.size(traindata1,0) )
    numtestdata =  int( np.size(testdata1,0) )
    traindata = np.asarray(traindata1)
    testdata = np.asarray(testdata1)
    predlabels = np.zeros((numtestdata,1))
    K =  np.zeros((numtestdata,numtraindata))
    for j in range(0,numtestdata):
        for i in range(0,numtraindata):
            K[j,i] = kernel(traindata[i,:],testdata[j,:],p)
    predlabels = np.dot(K,alphas)

    return predlabels


from ..monte_carlo import monteCarloSkeleton, monteCarloStats

import numpy as np

def blackScholes(current: float, volatility: float, ttm: float, strike: float,
                 rf: float, dividend: float, sim_count: int, eval_count: int,
                 opt_type: str='C', **kwargs) -> dict:
    """Function to model the price of a European Option, under the Black-Scholes
    pricing model heuristic, using a Monte-Carlo simulation.

    This function simulates a simple Geometric Brownian Motion (GBM) of the
    underlying asset price, before computing the terminal contract value for a
    given number of simulated paths.

    Then, Monte Carlo simulation statistics are
    computed for each of the simulations, and a dict of results is returned.

    Arguments:
        current {float} -- Current price of the underlying asset.
        volatility {float} -- Volatility of the underlying asset price.
        ttm {float} -- Time to expiration (in years).
        strike {float} -- Strike price of the option contract.
        rf {float} -- Risk-free rate (annual).
        dividend {float} -- Dividend yield (annual).
        sim_count {int} -- Number of paths to simulate.
        eval_count {int} -- Number of evaluations per path simulation.

    Keyword Arguments:
        opt_type {str} -- Option type; must be 'C' or 'P' (default: {'C'}).

    Raises:
        ValueError: Raised if `opt_type` is not 'C' or 'P'.

    Returns:
        dict -- Formatted dictionary of Monte Carlo simulation results.
    """

    # Verify option type choice
    if opt_type not in ['C', 'P']:
        raise ValueError('Incorrect option type; must be "C" or "P".')

    # Computing delta t
    dt = ttm / eval_count
    # Computing intitial value
    init_val = np.log(current)
    # Computing nudt
    nudt = (rf - dividend - (np.power(volatility, 2) / 2)) * dt

    # Defining lambda function to model Geometric Brownian Motion (GBM)
    gbm = lambda x: nudt + (volatility * np.sqrt(dt) * x)

    # Defining simulation function
    def sim_func(x: np.array) -> float:
        if (opt_type == 'C'):
            # Call option
            return np.exp(-1 * rf * ttm) * \
                np.maximum(np.exp(init_val + np.sum(gbm(x))) - strike, 0)
        else:
            # Put option
            return np.exp(-1 * rf * ttm) * \
                np.maximum(strike - np.exp(init_val + np.sum(gbm(x))), 0)

    # Running simulation
    mc_output = monteCarloSkeleton(sim_count=sim_count,
                                   eval_count=eval_count,
                                   sim_func=sim_func)

    # Computing and returning sample statistics
    return monteCarloStats(mc_output=mc_output)


import numpy as np
import math

aa = 1.5
a = np.array([
    [5.18+aa, 1.12,    0.95,    1.32,    0.83],
    [1.12,    4.28-aa, 2.12,    0.57,    0.91],
    [0.95,    2.12,    6.13+aa, 1.29,    1.57],
    [1.32,    0.57,    1.29,    4.57-aa, 1.25],
    [0.83,    0.91,    1.57,    1.25,    5.21+aa]
])

epsilon = 10e-4

print("------------")
print("   Task 1   ")
print("------------")

# Find max abs eigenvalue and corresponding eigenvector
def power_iteration(a, epsilon):
    x_next = np.ones(a.shape[0])
    mu = np.nan
    mu_next = np.nan

    step = 0

    while not abs(mu_next - mu) < epsilon:
        step += 1
        x = x_next
        mu = mu_next

        x /= np.linalg.norm(x)
        x_next = a @ x
        mu_next = x_next @ x
        #print(f'x = {x}, x_next = {x_next}')

    print(f"(Steps: {step})")

    return (mu_next, x_next / np.linalg.norm(x_next))

# Alias
get_eigen_max = power_iteration

# Find max abs eigenvalue, knowing min abs eigenvalue
# a must be symmetrical
def get_eigenvalue_min(a, epsilon, eigenvalue_max=None):
    if eigenvalue_max:
        b = np.eye(a.shape[0]) * eigenvalue_max - a
        return eigenvalue_max - power_iteration(b, epsilon)[0]
    else:
        a_max = np.max(a)
        b = a_max * np.eye(a.shape[0]) - a
        return a_max - power_iteration(b, epsilon)[0]

# Find max abs eigenvalue and corresponding eigenvector
def get_eigen_min(a, epsilon):
    a_inv = np.linalg.inv(a)
    eigenvalue_min = 1 / get_eigen_max(a_inv, epsilon)[0]

    x = np.ones(a.shape[0])

    while True:
        x_next = a_inv @ x * eigenvalue_min

        if (np.allclose(x, x_next, atol=epsilon)):
            return (eigenvalue_min, x_next / np.linalg.norm(x_next))

        x = x_next

print("Max. eigen. (power iteration): ")
eigenvalue_max, eigenvector_max = get_eigen_max(a, epsilon)
print(eigenvalue_max, eigenvector_max)

print("Min. eigenvalue (power iteration, from max. eigenvalue): ")
print(get_eigenvalue_min(a, epsilon, eigenvalue_max))

print("Min. eigenvalue (power iteration): ")
print(get_eigenvalue_min(a, epsilon))

print("Min. eigen. (power iteration on inverse): ")
eigenvalue_min, eigenvector_min = get_eigen_min(a, epsilon)
print(eigenvalue_min, eigenvector_min)

print("------------")
print("   Task 2   ")
print("------------")

def jacobi_rotation_method(a, epsilon):
    u_prod = np.eye(a.shape[0])

    # Quadratic sum of non-diagonal elements
    t = 0
    for i in range(a.shape[0]):
        for j in range(i, a.shape[1]):
            if i != j:
                t += 2 * (a[i, j] ** 2)

    step = 0

    while t > epsilon:
        step += 1
        # Find max. abs. non-diagonal element
        max_nd = 0

        for i in range(a.shape[0]):
            for j in range(a.shape[1]):
                if i != j and abs(a[i, j]) > abs(max_nd):
                    max_nd = a[i, j]
                    i_max_nd = i
                    j_max_nd = j

        if abs(a[i_max_nd, i_max_nd] - a[j_max_nd, j_max_nd]) < epsilon:
            phi = math.pi / 4
        else:
            phi = math.atan(2 * max_nd /
                    (a[i_max_nd, i_max_nd] - a[j_max_nd, j_max_nd])) / 2

        u = np.eye(a.shape[0])
        u[i_max_nd, i_max_nd] = math.cos(phi)
        u[i_max_nd, j_max_nd] = math.sin(phi)
        u[j_max_nd, i_max_nd] = -math.sin(phi)
        u[j_max_nd, j_max_nd] = math.cos(phi)
        t -= 2 * (max_nd ** 2)
        #print(t)

        #a = u.transpose() @ a @ u
        a = u @ a @ u.transpose()
        #u_prod = u_prod @ u
        u_prod = u_prod @ u.transpose()

    print(f"(Steps: {step})")

    return (np.diag(a), u_prod)

get_eigen = jacobi_rotation_method

print("Eigenvectors (Jacobi rotations):")
eigenvalues, eigenvectors = get_eigen(a, epsilon)
print(eigenvalues)
print(eigenvectors)

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

numpy_eigenvalues, numpy_eigenvectors = np.linalg.eig(a)
print("np.linalg.eig: ")
print(numpy_eigenvalues)
print(numpy_eigenvectors)


import numpy as np
import matplotlib.pyplot as plt

def gd(x_start, step, g):
    x = x_start
    xarr = [x]
    for i in range(20):
        grad = g(x)
        x -= grad * step
        xarr.append(x.copy())
        print '[ Epoch {0} ] grad = {1}, x = {2}'.format(i, grad, x)
        if sum(abs(grad)) < 1e-6:
            break;
    return x, xarr

def momentum(x_start, step, g, discount = 0.7):
    x = np.array(x_start, dtype='float64')
    pre_grad = np.zeros_like(x)
    xarr = [x.copy()]
    for i in range(50):
        grad = g(x)
        pre_grad = pre_grad * discount + grad * step
        x -= pre_grad
        xarr.append(x.copy())

        print '[ Epoch {0} ] grad = {1}, x = {2}'.format(i, grad, x)
        if sum(abs(grad)) < 1e-6:
            break;
    return x, xarr

def f(x):
    return x[0] * x[0] + 50 * x[1] * x[1]
def g(x):
    return np.array([2 * x[0], 100 * x[1]])
xi = np.linspace(-200,200,1000)
yi = np.linspace(-100,100,1000)
X,Y = np.meshgrid(xi, yi)
Z = X * X + 50 * Y * Y

def contour(X,Y,Z, arr = None):
    plt.figure(figsize=(15,7))
    xx = X.flatten()
    yy = Y.flatten()
    zz = Z.flatten()
    plt.contour(X, Y, Z, colors='black')
    plt.plot(0,0,marker='*')
    if arr is not None:
        arr = np.array(arr)
        for i in range(len(arr) - 1):
            plt.plot(arr[i:i+2,0],arr[i:i+2,1])
    plt.show()

contour(X,Y,Z)

# normal step
res, x_arr = gd([150,75], 0.016, g)
contour(X, Y, Z, x_arr)

# large step
res, x_arr = gd([150,75], 0.019, g)
contour(X, Y, Z, x_arr)

# extreme step
res, x_arr = gd([150,75], 0.02, g)
contour(X, Y, Z, x_arr)

# momentum
res, x_arr = momentum([150,75], 0.016, g)
contour(X, Y, Z, x_arr)

def nesterov(x_start, step, g, discount = 0.7):
    x = np.array(x_start, dtype='float64')
    pre_grad = np.zeros_like(x)
    x_arr = [x.copy()]
    for i in range(50):
        x_future = x - step * discount * pre_grad
        grad = g(x_future)
        pre_grad = pre_grad * 0.7 + grad
        x -= pre_grad * step
        x_arr.append(x.copy())

        print '[ Epoch {0} ] grad = {1}, x = {2}'.format(i, grad, x)
        if abs(sum(grad)) < 1e-6:
            break;
    return x, x_arr

res, x_arr = nesterov([150, 75], 0.012, g)
contour(X, Y, Z, x_arr)


# This code solves the problem of finding out the fourier transform for the
# function g(t) = A[u(t) - u(t-T)]

'''By the knowledge of fundamental concepts of
 fourier transform of unit function and time-shifting property
 '''
# WE KNOW THAT THE FINAL FOURIER TRANSFORM LOOKS LIKE
# G(iw) = A(1-exp(-iwT))(pi*delta(w) + 1/jw)

# IMport Modules
import numpy as np
import math
import matplotlib.pyplot as plt

def delta_function(w):
    if w == 0:
        return 1
    else:
        return 0

def imag_part_function_definer(A, w, T):
    return np.imag((A*(1-(np.exp(-1j*w*T))*(np.pi*delta_function(w) + (1/(1j*w))))))

def real_part_function_definer(A, w, T):
    return np.real((A*(1-(np.exp(-1j*w*T))*(np.pi*delta_function(w) + (1/(1j*w))))))

def imag_fourier_transform(low_frequency_range , high_frequency_range, T):
    pi = np.pi
    low_angular_frequency_range = 2*pi*low_frequency_range
    high_angular_frequency_range = 2*pi*high_frequency_range

    frequency_timestamps = np.linspace(low_angular_frequency_range, high_angular_frequency_range, 10000).flatten()

    y_values = [imag_part_function_definer(A = 10, w= w, T= T) for w in frequency_timestamps ]

    return (frequency_timestamps, y_values)

def real_fourier_transform(low_frequency_range , high_frequency_range, T):
    pi = np.pi
    low_angular_frequency_range = 2*pi*low_frequency_range
    high_angular_frequency_range = 2*pi*high_frequency_range

    frequency_timestamps = np.linspace(low_angular_frequency_range, high_angular_frequency_range, 10000).flatten()

    y_values = [real_part_function_definer(A = 10, w= w, T= T) for w in frequency_timestamps ]

    return (frequency_timestamps, y_values)

def imag_plotter():
    plt.plot(imag_fourier_transform(-10e+8,10e+8, 1)[0], imag_fourier_transform(-10e+8, 10e+8, 1)[1])
    plt.grid()
    plt.xlabel('VALUES OF FREQUENCY')
    plt.ylabel('IMAGINARY PART')

def real_plotter():
    plt.plot(real_fourier_transform(-10e+8,10e+8, 1)[0], real_fourier_transform(-10e+8, 10e+8, 1)[1])
    plt.grid()
    plt.xlabel('VALUES OF FREQUENCY')
    plt.ylabel('REAL PART')

if __name__ == "__main__":
   # Plotting both the real and imaginary parts with sub-plots on the same plot

    fig, (ax1, ax2) = plt.subplots(2, 1)
    ax1.plot(imag_fourier_transform(-10e+8,10e+8, 1)[0], imag_fourier_transform(-10e+8, 10e+8, 10e+3)[1])
    ax1.set_xlabel('VALUES OF FREQUENCY')
    ax1.set_ylabel('IMAGINARY PART')
    ax1.grid()

    ax2.plot(real_fourier_transform(-10e+8,10e+8, 1)[0], real_fourier_transform(-10e+8, 10e+8, 10e+3)[1])
    ax2.set_xlabel('VALUES OF FREQUENCY')
    ax2.set_ylabel('REAL PART')
    ax2.grid()

    plt.show()


import numpy as np

# Resting stance

# w - foot position away from hip servo / body at resting/neutral stance
# h - height form the floor
# A - upper leg length
# B - lower leg length
# theta = theta1 = theta2
# theta1 = angle of upper leg wrt to the horizontal
# theta2 = angle of the lower leg wrt to line perpendicular to the upper leg

def find_resting_stance_foot_position(theta, A=86, B=128):
  angle = np.radians(theta)
  w = A*np.cos(angle)
  h = B - A*np.sin(angle)
  return w, h

# propelling forward
# y - foot position from hip servo / body at sidestep stance
# v - foot position from hip servo / body at reaching stance
# beta - reach hip angle (theta in figure) (hip angle at reaching stance)
# alpha - sidestep hip angle (hip angle at side step stance)
# w - foot position away from the body at neutral/resting stance

def find_propel_forward_values(alpha, w):
  k = w*np.cos(np.radians(45)) # cos(45) == sin(45)
  alpha = np.radians(alpha)
  y = k / np.cos(alpha)
  c = k*np.tan(alpha) #  y * np.sin(alpha)
  m = (2*k + c) / k
  beta = np.arctan(m)
  v = k / np.cos(beta)
  return np.degrees(beta), v, y

# side step stance or reaching stance
# A - upper leg length
# B - lower leg length
# w - foot position away from hip servo / body at stance (reaching or sidestep stance)
# h - height form the floor
# theta1 = angle of upper leg wrt to the horizontal
# theta2 = angle of the lower leg wrt to line perpendicular to the upper leg
def find_stance_angles(w, h, A=86, B=128):
  C = np.sqrt(h**2 + w**2)
  x = np.arcsin(w / C)

  cos_gamma = (A**2 + B**2 - C**2) / (2*A*B)
  gamma = np.arccos(cos_gamma)
  cos_y = (A**2 + C**2 - B**2) / (2*A*C)

  y = np.arccos(cos_y)

  theta1 = x + y - np.radians(90)
  theta2 = np.radians(90) - gamma
  return np.degrees(theta1), np.degrees(theta2)

# A - upper leg length
# B - lower leg length
A = 86
B = 128

# theta1 = angle of upper leg wrt to the horizontal
# theta2 = angle of the lower leg wrt to line perpendicular to the upper leg

# beta - hip angle at reaching stance
# alpha - hip angle at side step stance

# theta = theta1 = theta2 angles at resting stance
THETA = 40 # Between 30 and 50
ALPHA = 5 # Between 0 and 20

w_resting, h = find_resting_stance_foot_position(THETA, A, B)
# w_resting - foot position away from hip servo / body at resting stance
# h - height from the floor (at resting stance)

# y_side_step - foot position from hip servo / body at sidestep stance
# v - foot position from hip servo / body at reaching stance
# beta - hip angle at reaching stance
BETA, v_reach, y_sidestep = find_propel_forward_values(ALPHA, w_resting)

theta1_sidestep, theta2_sidestep = find_stance_angles(y_sidestep, h, A, B)
theta1_reach, theta2_reach = find_stance_angles(v_reach, h, A, B)

print('Upper leg length in mm: ', A)
print('Lower leg length in mm: ', B)
print('Height from floor in mm: ', h)

print('-')
print("RESTING STANCE")
print("hip angle parallel to (shoulder) horizontal in degrees: 45")
print('knee angle parallel to (shoulder) horizonal in degrees: ', THETA)
print('ankle angle perpendicular to lowerleg in degrees: ', THETA)
print('foot position from hip in mm: ', w_resting)

print('-')
print("SIDESTEP STANCE")
print("hip angle parallel to (shoulder) horizontal in degrees:", ALPHA)
print('knee angle parallel to (shoulder) horizonal in degrees:', theta1_sidestep)
print('ankle angle perpendicular to lowerleg in degrees:', theta2_sidestep)
print('foot position from hip in mm: ', y_sidestep)

print('-')
print("REACHING STANCE")
print("hip angle parallel to (shoulder) horizontal in degrees:", BETA)
print('knee angle parallel to (shoulder) horizonal in degrees:', theta1_reach)
print('ankle angle perpendicular to lowerleg in degrees:', theta2_reach)
print('foot position from hip in mm: ', v_reach)

#neutral hip angle is 45
NEUTRAL = 45
hip_angle_resting = 0
hip_angle_sidestep = ALPHA + NEUTRAL
hip_angle_reach = BETA - NEUTRAL

print('-')
print("Absolute hip angles based on servo orientation (degrees):")
print("resting: ", hip_angle_resting)
print("side_step: ", hip_angle_sidestep)
print("reaching: ", hip_angle_reach)

# Upper leg length in mm:  86
# Lower leg length in mm:  128
# Height from floor in mm:  72.72026556695762
# -
# RESTING STANCE
# hip angle parallel to (shoulder) horizontal in degrees: 45
# knee angle parallel to (shoulder) horizonal in degrees:  40
# ankle angle perpendicular to lowerleg in degrees:  40
# foot position from hip in mm:  65.8798221082321
# -
# SIDESTEP STANCE
# hip angle parallel to (shoulder) horizontal in degrees: 5
# knee angle parallel to (shoulder) horizonal in degrees: 38.58250661168782
# ankle angle perpendicular to lowerleg in degrees: 47.7826582117061
# foot position from hip in mm:  46.76201253161473
# -
# REACHING STANCE
# hip angle parallel to (shoulder) horizontal in degrees: 64.40350450294298
# knee angle parallel to (shoulder) horizonal in degrees: 35.24987500744083
# ankle angle perpendicular to lowerleg in degrees: 18.169817718893693
# foot position from hip in mm:  107.82585845793648
# -
# Absolute hip angles based on servo orientation:
# resting:  0
# side_step:  50
# reaching:  19.40350450294298


import numpy as np
from scipy.integrate import odeint
import matplotlib.pyplot as plt

#N Population Size
N = 1000
#Initial conditions and vector
I0 = 1
R0 = 0
S0 = 999
initial = S0, I0, R0
#time
t = np.linspace(0, 200, 200)

#SIR model
def SIRmodel(v, t, N, beta, gamma):
    """Determines three differential equations of the SIR model depending on initial
    conditions and chosen parameters. dSdt determines the rate of change of
    those that are not infected but are susceptible to being infected. dIdt
    determines the rate of change of the total infected individuals. dRdt
    determines the rate of change of the individuals who have recovered.

    Paramaters:
    v - vector of integers
    t - numeric sequence of form np.linspace(start, end, number of breakpoints)
    N - integer
    beta - float
    gamma - float

    Returns:
    Tuple of 3 floats, the change in the values of the differential
    equations of the model at one instant in time
    """
    S, I, R = v
    dSdt = (-1 * beta * S * I) / N
    dIdt = (beta * S * I / N) - (gamma * I)
    dRdt = gamma * I
    return dSdt, dIdt, dRdt

# Integrating and plotting the differential equations in the SIR model
def integrate_SIR(gamma, beta):
    """Plots the SIR model of disease for given gamma and beta parameters

    Parameters:
    gamma - float, reciprocal of average period of infectiousness
    beta - float, proportionality of how many people get into contact with the infected person.

    Returns:
    Plot of number of susceptible individuals, infected individuals, and
    recovered individuals over time
    """
    int_SIR = odeint(SIRmodel, initial, t, args=(N, beta, gamma))
    S, I, R = int_SIR.T

    # Plot S(t), I(t) and R(t)
    plt.plot(t, S, 'b', label='Susceptible Individuals')
    plt.plot(t, I, 'r', label='Infected Individuals')
    plt.plot(t, R, 'g', label='Recovered Individuals')
    plt.xlabel('Time (days)')
    plt.ylabel('Number of Individuals')
    plt.title('SIR Model of Disease Spread with \u03B3 = '+ str(round(gamma,2))+ ' \u03B2 = '+ str(beta))
    plt.legend()
    plt.show()

#Plotting for a variety of chosen beta and gamma parameters
integrate_SIR(1/10, 0.2)
integrate_SIR(1/10, 0.1)
integrate_SIR(1/7, 0.2)
integrate_SIR(1/14, 0.2)


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

from . import utils

def kge(simulated, observed):
    """
    Calculate the Kling-Gupta efficiency.

    Calculates the Kling-Gupta efficiency between two variables
    simulated and observed. The kge is calculated using the
    formula:

    KGE = 1 - sqrt((cc-1)**2 + (alpha-1)**2 + (beta-1)**2)

    where:
        cc = correlation coefficient between simulated and observed;
        alpha = std(simulated) / std(observed)
        beta = sum(simulated) / sum(observed)

    where s is the simulated values, o is the observed values, and
    N is the total number of values in s & o. Note that s & o must
    have the same number of values.

    Kling-Gupta efficiency can range from -infinity to 1. An efficiency of 1 (E
    = 1) corresponds to a perfect match of model to observed data.
    Essentially, the closer the model efficiency is to 1, the more accurate the
    model is.

    The efficiency coefficient is sensitive to extreme values and might yield
    sub-optimal results when the dataset contains large outliers in it.

    Kling-Gupta efficiency can be used to quantitatively describe the accuracy
    of model outputs. This method can be used to describe the predictive
    accuracy of other models as long as there is observed data to compare the
    model results to.

    Input:
    simulated : simulated values
    observed : observed values

    Output:
    kge : Kling-Gupta Efficiency
    """
    # Check that dimensions of simulated and observed fields match
    utils.check_arrays(simulated, observed)

    alpha = np.std(simulated) / np.std(observed)
    beta = np.sum(simulated) / np.sum(observed)
    cc = np.corrcoef(observed, simulated)[0, 1]

    # Calculate the kge
    kge = 1.0 - np.sqrt((cc - 1.0) ** 2 + (alpha - 1.0) ** 2 + (beta - 1.0) ** 2)

    return kge


# -*- coding: utf-8 -*-
"""
Created on Fri Dec 22 15:17:39 2017

@author: Anastasios Tzavellas
"""

import numpy as np
import integration

def f(x):
    return np.power(x, 2) + np.power(x, 5)

IAnalytic = np.power(3, 3) / 3 + np.power(3, 6) / 6
print('Analytic')
print('Integral:', IAnalytic)

a = 0.
b = 3.
epsilon = 1e-2
trapezoid = integration.trapezoid(f, a, b, epsilon)
ITrapezoid = trapezoid['integral']
itTrapezoid = trapezoid['iterations']
print('\nTrapezoid')
print(trapezoid)
print('Deviation:', np.abs(IAnalytic - ITrapezoid))

simpson = integration.simpson(f, a, b, epsilon)
ISimpson = simpson['integral']
itSimpson = simpson['iterations']
print('\nSimpson 1/3')
print(simpson)
print('Deviation:', np.abs(IAnalytic - ISimpson))


import numpy as np
import scipy

__all__ = ['ar_yule_walker']

from ... import operators
from ... import utilits as ut

#------------------------------------------------------------------
def ar_yule_walker(x, order, mode='straight', unbias = False):
    '''
    Yule-Walker method for AutoRegressive (AR) model approximation.

    Parameters
    --------------
    * x: 1d ndarray,
        1-d input ndarray;
    * order: int,
        is the order of the desired model;
    * mode: string,
        mode of correlation function,
        mode = {full, same, straight}.
    * unbias: bool,
        if True, unbiased covariance function will be taken.

    Returns
    ------------------
    * a: 1d ndarray (complex (or float)),
        autoregression coefficients.
    * noise_variace: complex (or float),
        variance of model residulas.

    Notes
    ---------
    * If mode 'full',
        array of doubled size will be returned.
    * Yule-Walker method:
      ..math::
      r1 = -toeplitz(r_0,...r_{p-1})A^T,

      where
      * r  = [r_0,r_1,...r_{p-1}]
          - autocorrelation coefficients;
      * r1 = [r_1,r_1,...r_p]^T
          -set of required approximation results;
      * p  is the model order;
      * toeplitz is the operator
          for obtaining toeplitz matrix from vector;
      * A={a_1,...,a_p}
          are the approcimation coefficients
                                      of autoregression model
        with the order p, in the following form:
        r_m = \sum_{k=1}^p {a_k r_{m-k}}+\sigma^2
        where \sigma^2
            is the ewsidual noise, which can be calulated as
        \sigma = sqrt(r_0 + \sum(r_1^* \cdot a)).

    Examples
    --------------

    References
    -------------
    [1a] P. Stoica, R.L.
        Moses, Spectral analysis of signals
        - New-York: Present-Hall, 2005.
    [1b] http://www2.ece.ohio-state.edu/~randy/SAtext/
        - Dr.Moses Spectral Analysis of Signals: Resource Page
    [2a] M.H. Hayes.
        Statistical Digital Signal Processing and Modeling,
        John Wiley & Sons, 1996.
    [2b] https://www.mathworks.com/matlabcentral/fileexchange/
        2183-statistical-digital-signal-processing-and-modeling
    [3]  S.L. Marple, Digital spectral analysis with applications.
                                – New-York: Present-Hall, 1986.

    See also
    ----------
    toeplitz;
    covar;
    levenson_durbin;
    burg.

    '''
    x = np.asarray(x)
    N = x.shape[0]

    r  = operators.correlation(x, y=None, mode=mode,
                            take_mean=False, unbias=unbias)

    rn = scipy.linalg.toeplitz(r[:order])

    r1 = r[1:order + 1]

#     a  = np.dot(np.linalg.inv(rn),r1)
    a = scipy.linalg.lstsq(rn,r1)[0]
    noise_var = np.real(r[0] - np.dot(np.conj(r1),a))

    a = np.append(1,-a)

    return a, noise_var


# shows how linear regression analysis can be applied to 2-dimensional data
#
# notes for this course can be found at:
# https://deeplearningcourses.com/c/data-science-linear-regression-in-python
# https://www.udemy.com/data-science-linear-regression-in-python

#from __future__ import print_function, division
#from builtins import range
# Note: you may need to update your version of future
# sudo pip install -U future

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

# load the data
X = []
Y = []
for line in open('data_2d.csv'):
    x1, x2, y = line.split(',')
    X.append([float(x1), float(x2), 1]) # add the bias term
    Y.append(float(y))

# let's turn X and Y into numpy arrays since that will be useful later
X = np.array(X)
Y = np.array(Y)

# let's plot the data to see what it looks like
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.scatter(X[:,0], X[:,1], Y)
plt.show()

# apply the equations we learned to calculate a and b
# numpy has a special method for solving Ax = b
# so we don't use x = inv(A)*b
# note: the * operator does element-by-element multiplication in numpy
#       np.dot() does what we expect for matrix multiplication
w = np.linalg.solve(np.dot(X.T, X), np.dot(X.T, Y))
Yhat = np.dot(X, w)

# determine how good the model is by computing the r-squared
d1 = Y - Yhat
d2 = Y - Y.mean()
r2 = 1 - d1.dot(d1) / d2.dot(d2)
print("the r-squared is:", r2)


# import cython
from scipy.special import erf
from numpy import log, exp, sqrt

# cimport cython
# from libc.math cimport exp, sqrt, pow, log, erf
#
# @cython.cdivision(True)
# cdef double std_norm_cdf(double x) nogil:
#     return 0.5*(1+erf(x/sqrt(2.0)))
#
# @@cython.cdivision(True)
# def blsprice(double s, double k, double t, double v,
#                  double rf, double div, double cp):
#     """Price an option using the Black-Scholes model.
#
#     s : initial stock price
#     k : strike price
#     t : expiration time
#     v : volatility
#     rf : risk-free rate
#     div : dividend
#     cp : +1/-1 for call/put
#     """
#     cdef double d1, d2, optprice
#     with nogil:
#         d1 = (log(s/k)+(rf-div+0.5*pow(v,2))*t)/(v*sqrt(t))
#         d2 = d1 - v*sqrt(t)
#         optprice = cp*s*exp(-div*t)*std_norm_cdf(cp*d1) - \
#             cp*k*exp(-rf*t)*std_norm_cdf(cp*d2)
#     return optprice

def std_norm_cdf(x):
    return 0.5*(1+erf(x/sqrt(2.0)))

def blsprice(s, k, rf, t, v, div=0, cp=1):
    d1 = (log(s / k) + (rf - div + 0.5*pow(v, 2)) * t) / (v * sqrt(t))
    d2 = d1-v*sqrt(t)
    optprice = cp*s*exp(-div*t)*std_norm_cdf(cp*d1) - \
           cp*k*exp(-rf*t)*std_norm_cdf(cp*d2)
    return optprice


#Lucas number

def LucasNumber(index,roundi=True):
    from sympy import Pow as mmmpow
    from sympy import Integer as mmmint
    from sympy import N as mmmrat
    b = (mmmpow(((1+5**(1/2))/2),index))+(mmmpow(((1-5**(1/2))/2),index))
    if(not roundi):
        return mmmint(b)
    else:
        return mmmrat(b)

def LucasSequence(countt,returni=True):
    s = [2,1]
    for n in range(2,countt):
        s.append(s[n-1]+s[n-2])
    if(returni):
        return s
    else:
        print(s)

def isPrime_Lucas(p,returnNums=True,roundi=True):
    l = LucasNumber(p,roundi)
    if((l-1)%p!=0):
        if(returnNums):
        	return l
        else:
        	return True
    return False

def doTest(toPrint=False,toProgress=False,start=0,toEnd=1000,algo="s"):
    s=set()
    KK=10000
    from IPython.display import clear_output
    for i in range(start,toEnd+1):
        if(toProgress and (i<KK or (i>=KK and i%(KK/100)==0))):
            clear_output(wait=True)
            print(i,end="\t")
        if(algo=="s"):
            lucas = LucasNumber(i)
        elif(algo=="prime"):
            lucas = isPrime_Lucas(i)
        if(lucas):
            s.add(lucas)
            if(toPrint and not toProgress):
                print(lucas,end=", ")
        if(toProgress and (i<KK or (i>=KK and i%(KK/100)==0))):
            print(s)
    if(not toPrint):
        return s

#LucasNumber(0)
#doTest(True,False,0,800) #1.69 s
#LucasSequence(800) #30 ms
#isPrime_Lucas(10)
#doTest(False,False,1,10000,"prime")


import numpy as np
import matplotlib.pyplot as plt

N=51
initial=-np.pi
final=np.pi
x=np.linspace(initial,final,N)
h=(final-initial)/(N-1)

#analytic:
y_ana=np.sin(x)
dy_ana=np.cos(x)
ddy_ana=-np.sin(x)

ddy_3=[]
for i in range(1,N-1):
    ddy_3.append((y_ana[i+1]-2*y_ana[i]+y_ana[i-1])/h/h)

x3=np.delete(x,[0,N-1])

plt.plot(x,ddy_ana)
plt.plot(x3,ddy_3,'r.',label="three points")
plt.show()

error3=(abs(ddy_3-ddy_ana[1:N-1]))
plt.plot(x3,error3,label="three points")
plt.title("error by using different number of points")
plt.legend()
plt.show()


import numpy as np
import math

## Integrand function
def f(x): return x**5+x**4

## 1st Interval
a=-1.0
b=-0.4
n1=100
x1=np.random.uniform(a,b,n1)  # [a,b]=[-1.0,-0.4]
k=np.linspace(0.35,1,50)
eval_funct1=f(x1)
n1=n1*1.0
i1=(b-a)*(np.sum(eval_funct1)/n1) # mean
mu_camp1=(np.sum(eval_funct1))/n1
var_camp1=(1/(n1-1))*np.sum((eval_funct1-mu_camp1)**2)  # variance
var1=(b-a)**2*(1/n1)*var_camp1

## 2nd Interval
a=-0.4
b=0.4
n2=100
x2=np.random.uniform(a,b,n2)  # [a,b]=[-0.4,0.4]
eval_funct2=f(x2)
n2=n2*1.0
i2=(b-a)*(np.sum(eval_funct2)/n2) # mean
mu_camp2=(np.sum(eval_funct2))/n2
var_camp2=1/(n2-1)*np.sum((eval_funct2-mu_camp2)**2)  # variance
var2=(b-a)**2*(1/n2)*var_camp2

## 3rd Interval
a=0.4
b=0.6
n3=800
x3=np.random.uniform(a,b,n3)  # [a,b]=[0.4,0.6]
eval_funct3=f(x3)
n3=n3*1.0
i3=(b-a)*(np.sum(eval_funct3)/n3) # mean
mu_camp3=(np.sum(eval_funct3))/n3
var_camp3=1/(n3-1)*np.sum((eval_funct3-mu_camp3)**2)  # variance
var3=(b-a)**2*(1/n3)*var_camp3

## 4th Interval
a=0.6
b=0.7
n4=1000
x4=np.random.uniform(a,b,n4)  # [a,b]=[0.6,0.7]
eval_funct4=f(x4)
n4=n4*1.0
i4=(b-a)*(np.sum(eval_funct4)/n4) # mean
mu_camp4=(np.sum(eval_funct4))/n4
var_camp4=1/(n4-1)*np.sum((eval_funct4-mu_camp4)**2)  # variance
var4=(b-a)**2*(1/n4)*var_camp4

## 5th Interval
a=0.7
b=0.8
n5=1500
x5=np.random.uniform(a,b,n5)  # [a,b]=[0.7,0.8]
eval_funct5=f(x5)
n5=n5*1.0
i5=(b-a)*(np.sum(eval_funct5)/n5) # mean
mu_camp5=(np.sum(eval_funct5))/n5
var_camp5=1/(n5-1)*np.sum((eval_funct5-mu_camp5)**2)  # variance
var5=(b-a)**2*(1/n5)*var_camp5

## 6th Interval
a=0.8
b=0.9
n6=3000
x6=np.random.uniform(a,b,n6)  # [a,b]=[0.8,0.9]
eval_funct6=f(x6)
n6=n6*1.0
i6=(b-a)*(np.sum(eval_funct6)/n6) # mean
mu_camp6=(np.sum(eval_funct6))/n6
var_camp6=1/(n6-1)*np.sum((eval_funct6-mu_camp6)**2)  # variance
var6=(b-a)**2*(1/n6)*var_camp6

## 7th Interval
a=0.9
b=1.0
n7=3500
x7=np.random.uniform(a,b,n7)  # [a,b]=[0.9,1]
eval_funct7=f(x7)
n7=n7*1.0
i7=(b-a)*(np.sum(eval_funct7)/n7) # mean
mu_camp7=(np.sum(eval_funct7))/n7
var_camp7=1/(n7-1)*np.sum((eval_funct7-mu_camp7)**2)  # variance
var7=(b-a)**2*(1/n7)*var_camp7

## Results
print(n1+n2+n3+n4+n5+n6+n7,'Check on total number of generations [has to be 10^4]')

S=i1+i2+i3+i4+i5+i6+i7
print(S,'Total mean for S, with Stratified Sampling')

var=var1+var2+var3+var4+var5+var6+var7
print(var ,'Total variance for S, with Stratified Sampling')

dev = sqrt(var)
print(dev ,'Total standard deviation for S, with Stratified Sampling')


import numpy as np

def rk2(t, y, h, f):
    k_1 = h*f(t,y)
    k_2 = h*f(t + h/2.0, y+k_1/2.0)
    y = y + k_2
    return y

def rk4(t, y, h, f):
    k_1 = h*f(t,y)
    k_2 = h*f(t + h/2.0, y + k_1/2.0)
    k_3 = h*f(t + h/2.0, y + k_2/2.0)
    k_4 = h*f(t + h, y + k_3)
    y = y + (1.0/6.0)*(k_1 + 2.0*k_2 + 2.0*k_3 +k_4)
    return y

def rk45(t, y, h, f, err_tol, h_min, h_max):
    k_1 = h*f(t, y)
    k_2 = h*f(t + h/4.0, y + k_1/4.0)
    k_3 = h*f(t + 3.0*h/8.0, y + 3.0*k_1/32.0 +9.0*k_2/32.0)
    k_4 = h*f(t + 12.0*h/13.0, y+1932.0*k_1/2197.0 - 7200.0*k_2/2197.0 +7296.0*k_3/2197.0)
    k_5 = h*f(t + h, y + 439.0*k_1/216.0 - 8.0*k_2 + 3680.0*k_3/513.0 -845.0*k_4/4104.0)
    k_6 = h*f(t + h/2.0, y - 8.0*k_1/27.0 + 2.0*k_2 - 3544.0*k_3/2565.0 + 1859.0*k_4/4104.0 - 11.0*k_5/40.0)
    Y = y + 25.0*k_1/216.0 + 1408.0*k_3/2565.0 + 2197.0*k_4/4101.0 - k_5/5.0
    Z = y + 16.0*k_1/135.0 + 6656.0*k_3/12825.0 +28561.0*k_4/56430.0 - 9.0*k_5/50.0 + 2.0*k_6/55.0
    err = np.abs(Z - Y)
    if (err[0] == 0 or err[1] == 0):
        s = 0.0
    else:
        s = 0.84*np.power(err_tol*h/err[0], 0.25)
    if (s < 0.75 and h > 2*h_min):
        h /= 2.0
    elif (s > 1.5 and h < h_max/2.0):
        h *= 2.0
    return h,Z


import argparse
import sys
import numpy as np
import csv

parser = argparse.ArgumentParser(
        description='sum the integers at the command line')
parser.add_argument(
    "-equation_coefficients",
    "--coeffs",
    required=False,
    help='a csv file with coefficients of linear system to solve')
parser.add_argument(
    "-n_unknowns",
    "--n",
    required=False,
    help='number of uknowns')

def gaussian_elimination(args):
    # promt user for input if none provided
    if not args.n:
        n = input("Number of unknowns: ")
        n = int(n)
    else:
        n = int(args.n)
    AugM = np.zeros((n,n+1))
    Soln = np.zeros(n)

    if not args.coeffs:
        print("Inputs needed for system in form Ax = B")
        for k in range(n):
            for j in range(n):
                AugM[k][j] = int(input(f"Enter coefficient for equation {k+1}, unknown {j+1}: "))
            AugM[k][n] = int(input(f"Enter solution for equation{k+1}: "))

    else:
        csv_file = args.coeffs
        with open(csv_file, newline='') as f:
            reader = csv.reader(f)
            for rdx, row in enumerate(reader):
                for idx, num in enumerate(row):
                    AugM[rdx][idx] = str(num)

    # Gaussian Elimination
    for k in range(n-1):
        if AugM[k][k] == 0:
            # need to choose a non-zero pivot row
            for i in range(k+1, n):
                if AugM[i][k] != 0:
                    # permute row s i and k
                    temp = AugM[i].copy()
                    AugM[i] = AugM[k]
                    AugM[k] = temp
                    break

        # Continue to get zero entries below diagonal
        for i in range(k+1, n):
            factor = AugM[i][k]/AugM[k][k]
            AugM[i] = AugM[i] - factor*AugM[k]

    # Check for existence of a solution
    for k in range(n):
        if AugM[k][k] == 0:
            print("No unique solution!")
            return

    # Back substitution
    Soln[n-1] = AugM[n-1][n]/AugM[n-1][n-1]
    for i in range(n-2, -1, -1):
        sum = np.matmul(AugM[i][i+1:n],Soln[i+1:])
        Soln[i] = (AugM[i][n] - sum)/AugM[i][i]

    print("Solution is : ", Soln)
    return Soln

if __name__== "__main__":

    args = parser.parse_args(sys.argv[1:])
    gaussian_elimination(args)


# -*- coding: utf-8 -*-
"""
Created on Wed Mar  4 09:53:57 2020

@author: Gualandi
"""

from pyomo.environ import ConcreteModel, Var, Objective, Constraint, SolverFactory
from pyomo.environ import maximize, Binary, RangeSet, PositiveIntegers

def MagicSquareSolver(n):
    # Create concrete model
    model = ConcreteModel()

    # Set of indices
    model.I = RangeSet(1, n)
    model.J = RangeSet(1, n)
    model.K = RangeSet(1, n*n)

    # Variables
    model.z = Var(within=PositiveIntegers)
    model.x = Var(model.I, model.J, model.K, within=Binary)

    # Objective Function
    model.obj = Objective(expr = model.z)

    def Unique(model, k):
        return sum(model.x[i,j,k] for j in model.J for i in model.I) == 1
    model.unique = Constraint(model.K, rule = Unique)

    def CellUnique(model, i, j):
        return sum(model.x[i,j,k] for k in model.K) == 1
    model.cellUnique = Constraint(model.I, model.J, rule = CellUnique)

    def Row(model, i):
        return sum(k*model.x[i,j,k] for j in model.J for k in model.K) == model.z
    model.row = Constraint(model.I, rule = Row)

    def Col(model, j):
        return sum(k*model.x[i,j,k] for i in model.I for k in model.K) == model.z
    model.column = Constraint(model.J, rule = Col)

    model.diag1 = Constraint(expr = sum(k*model.x[i,i,k] for i in model.I for k in model.K) == model.z)
    model.diag2 = Constraint(expr = sum(k*model.x[i,n-i+1,k] for i in model.I for k in model.K) == model.z)

    # Write the LP model in standard format
    model.write("magic_{}.lp".format(n))

    # Solve the model
    sol = SolverFactory('glpk').solve(model)

    # CHECK SOLUTION STATUS

    # Get a JSON representation of the solution
    sol_json = sol.json_repn()
    # Check solution status
    if sol_json['Solver'][0]['Status'] != 'ok':
        return None
    if sol_json['Solver'][0]['Termination condition'] != 'optimal':
        return None

    return model.x

def PlotMagicSquare(x, n):
    # Report solution value
    import matplotlib.pyplot as plt
    import numpy as np
    import itertools

    sol = np.zeros((n,n), dtype=int)

    for i, j, k in x:
        if x[i,j,k]() > 0.5:
            sol[i-1,j-1] = k

    cmap = plt.get_cmap('Blues')

    plt.figure(figsize=(6,6))
    plt.imshow(sol, interpolation='nearest', cmap=cmap)
    plt.title("Magic Square, Size: {}".format(n))
    plt.axis('off')

    for i, j in itertools.product(range(n), range(n)):
        plt.text(j, i, "{:d}".format(sol[i, j]),
                 fontsize=24, ha='center', va='center')

    plt.tight_layout()
    plt.show()

# -----------------------------------------------
#   MAIN function
# -----------------------------------------------
if __name__ == "__main__":

    # Solve Magic Square of size 4
    n = 4

    x = MagicSquareSolver(n)
    if x:
        PlotMagicSquare(x, n)
    else:
        print("Unable to solve Magic Square of size", n)


from sympy import *
x = symbols('x')
x0 = 1
x_list = [x0]
i = 0
# func
f = lambda x : exp(x) - 1

while True:
    # 判断分母是否为0，如果是0直接跳出
    if diff(f(x),x).subs(x,x0) != 0:
        x0 = x0 - f(x0) / diff(f(x), x).subs(x, x0)
        x_list.append(x0)
    else:
        break
    if len(x_list) > 1:
        i += 1
        error = abs((x_list[-1] - x_list[-2]) / x_list[-1])
        if error < 10 ** (-4):
            print(f'迭代第{i}次后，误差小于10^(-8)，误差为{error}')
            break

print(f'所求方程式的根为{float(x_list[-1])}')


import numpy as np
import matplotlib.pyplot as plt

z = np.arange(-5,5,.1)

sigma_fn = np.vectorize(lambda  z : 1.0/(1.0+np.exp(-z))) #for each element do this and return
#y = 1.0/(1.0+np.exp(-z))
y = sigma_fn(z)

fig = plt.figure()

ax = fig.add_subplot(1,1,1)

ax.plot(z,y)
ax.set_xlim([-5,5])
ax.set_ylim([-0.5,1.5])
ax.set_title('Sigmoid Function')
ax.set_xlabel('z')
ax.grid(True)

plt.show()


import numpy as np
import matplotlib.pyplot as plt

# Hidden layers are best represented with non-linearity for deeper representations
# Sigmoid, tanh, RelU
# Output layers are generally used with Linear, sigmoid, softmax
# Multilayer Perceptron (MLP): ReLU activation function.
# Convolutional Neural Network (CNN): ReLU activation function.
# Recurrent Neural Network: Tanh and/or Sigmoid activation function.

# Sigmoid activation function (logistic fn)
# Outputs between 0, 1  succeptible to vanishing gradient problem
# scale input data to the range 0-1 (e.g. the range of the activation function) prior to training.
def sigmoid(z):
    soln = 1.0/(1.0+np.exp(-z))
    return(soln)

# Sigmoid derivative
def deriv_sigmoid(z):
    soln = sigmoid(z)*(1.0-sigmoid(z))
    return(soln)

# Tanh activation function
# Outputs -1, 1  succeptible to vanishing gradient problem
# scale input data to the range -1 to 1 (e.g. the range of the activation function) prior to training.
def tanh(z):
    soln = (np.exp(z) - np.exp(-z)) / (np.exp(z) + np.exp(-z))
    return(soln)

# tanh derivative
def deriv_tanh(z):
    soln = 1.0/((np.cosh(z))**2)
    return(soln)

# Relu activation function
# less susceptible to vanishing gradients that prevent deep models from being trained, although it can suffer from other problems like saturated or “dead” units.
# Normalize input data for 0-1 (good practice)
def ReLU(z):
    soln = np.maximum(0.0, z)
    return(soln)

# Relu derivative
def deriv_ReLU(z):
    if z > 0.0:
        return(1.0)
    else:
        return(0.0)

# Linear activation function (identity)
def linear(z):
    return(z)

def deriv_linear(z):
    return(1)

# Softmax
# outputs a vector of values that sum to 1.0 that can be interpreted as probabilities of class membership.
# Target labels used to train a model with the softmax activation function in the output layer will be vectors with 1 for the target class and 0 for all other classes.
def softmax(z):
    soln_vector = np.array([])
    for element in z:
        soln = np.exp(element) / np.exp(z).sum()
        soln_vector = np.append(soln_vector, soln)
    return(soln_vector)

# partial derivative of the i-th output w.r.t. the j-th input (input = j_vector, output = i_vector)
def deriv_softmax(soft_in_j, soft_out_i):
    soln_matrix = np.array([])
    for i in range(soft_out_i.size):            # iterate through i and j
        row = np.array([])
        for j in range(soft_in_j.size):
            if i == j:                          # Calculate delta
                delta = 1
            else:
                delta = 0

            soln = soft_out_i[i]*(delta-soft_out_i[j])          # soln Find element value
            row = np.append(row, soln)                          # Append until row is complete
        soln_matrix = np.append(soln_matrix, row)               # append row to soln_matrix
    soln_matrix = soln_matrix.reshape((soft_out_i.size, soft_in_j.size)) #reshape to ixj 2D matrix
    return(soln_matrix)

# Function plots

# define input data
#inputs = [x for x in range(-10, 10)]
#sigmoid_out = [sigmoid(x) for x in inputs]
#tanh_out = [tanh(x) for x in inputs]
#ReLU_out = [ReLU(x) for x in inputs]
#linear_out = [linear(x) for x in inputs]

# softmax is probability list and cannot be graphed
#soft_inputs = np.arange(5.0)
#softmax_out = softmax(soft_inputs)
#deriv_softmax(soft_inputs, softmax_out)

# Setup subplots

#plt.subplot(3,3,1)
#plt.title('Sigmoid')
#plt.plot(inputs, sigmoid_out)

#plt.subplot(3,3,2)
#plt.title('tanh')
#plt.plot(inputs, tanh_out)

#plt.subplot(3,3,3)
#plt.title('ReLU')
#plt.plot(inputs, ReLU_out)

#plt.subplot(3,3,4)
#plt.title('Linear')
#plt.plot(inputs, linear_out)

#plt.show()


import matplotlib.pyplot as plt
import numpy as np
import os
os.chdir('C:/Users/DELL/Desktop/Quant_macro')
import useful_functions as uf
######## parameters part 1 ##################
alpha = 1
rho2 = 1/100
rho1 = [1/0.2, 1/0.25]
Px = [lambda x, n=i: np.exp(-alpha*x)/(rho1[n] + rho2*np.exp(-alpha*x)) for i in range(len(rho1))]
order = 4
num_nodes = 6
size_grid = 300
func = uf.chebychev_pol(order)
grid = uf.cheb_node(0,10,size_grid)
nodes = uf.select_node(num_nodes, grid)

############################################

para = uf.find_theta_cheb(Px[0],nodes, order)
f_til = lambda x: sum(para[idx]* function(x) for idx, function in enumerate(func))
Px_0 = Px[0](grid)
poly = f_til(grid)
diff = np.abs(np.array(Px_0)-np.array(poly))
f, (ax,ax_diff) = plt.subplots(1,2)
f.set_figheight(5)
f.set_figwidth(10)
ax.plot(grid, Px_0, color='r', label='rho1=5')
ax.plot(grid, poly, color='b', label='poly_cub')
ax_diff.plot(grid, diff, color='b', label='diff_cub')
ax.set_xlabel('x')
ax.set_ylabel('f(x)')
ax.set_title('Chebyshev polynomial rho1 = 5')
ax_diff.set_xlabel('x')
ax_diff.set_ylabel('f(x)')
ax_diff.set_title('Chebyshev polynomial error')

################################################
para1 = uf.find_theta_cheb(Px[1],nodes,order)
f_til1 = lambda x: sum(para1[idx]* function(x) for idx, function in enumerate(func))
Px_1 = Px[1](grid)
poly1 = f_til1(grid)
diff1 = np.abs(np.array(Px_1)-np.array(poly1))
f1, (ax1, ax1_diff) = plt.subplots(1,2)
f1.set_figheight(5)
f1.set_figwidth(10)
ax1.plot(grid, Px_1, color='r', label='rho1=4')
ax1.plot(grid, poly1, color='b', label='poly_cub')
ax1_diff.plot(grid, diff1, color='b', label='diff_cub')
ax1.set_xlabel('x')
ax1.set_ylabel('f(x)')
ax1.set_title('Chebyshev polynomial rho1 = 4')
ax1_diff.set_xlabel('x')
ax1_diff.set_ylabel('f(x)')
ax1_diff.set_title('Chebyshev polynomial error')

g1, alx1 = plt.subplots(1,1)
g1.set_figheight(5)
g1.set_figwidth(10)
alx1.plot(grid, poly, color='r', label='rho1=5')
alx1.plot(grid, poly1, color='b', label='rho1=4')
alx1.set_xlabel('x')
alx1.set_ylabel('f(x)')
alx1.set_title('Chebyshev order 3 polynomial: 2 cases')

#########################################################
###################   monomials  5 ######################
#########################################################

######## parameters order 5 ##################

order_o5 = 6
func_o5 = uf.chebychev_pol(order_o5)
############################################

############################################
para_o5 = uf.find_theta_cheb(Px[0],nodes,order_o5)
f_til_o5 = lambda x: sum(para_o5[idx]* function(x) for idx, function in enumerate(func_o5))
poly_o5 = f_til_o5(grid)
diff_o5 = np.abs(np.array(Px_0)-np.array(poly_o5))
ax.plot(grid, poly_o5, color='g', label='poly_o5')
ax_diff.plot(grid, diff_o5, color='g', label='diff_o5')
################################################
para1_o5 = uf.find_theta_cheb(Px[1],nodes,order_o5)
f_til1_o5 = lambda x: sum(para1_o5[idx]* function(x) for idx, function in enumerate(func_o5))
poly1_o5 = f_til1_o5(grid)
diff1_o5 = np.abs(np.array(Px_1)-np.array(poly1_o5))
ax1.plot(grid, poly1_o5, color='g', label='poly_o5')
ax1_diff.plot(grid, diff1_o5, color='g', label='diff_o5')

g2, alx2 = plt.subplots(1,1)
g2.set_figheight(5)
g2.set_figwidth(10)
alx2.plot(grid, poly_o5, color='r', label='rho1=5')
alx2.plot(grid, poly1_o5, color='b', label='rho1=4')
alx2.set_xlabel('x')
alx2.set_ylabel('f(x)')
alx2.set_title('Chebyshev order 5 polynomial: 2 cases')
#########################################################
###################   monomials  10 ######################
#########################################################

######## parameters order 5 ################## diff = np.abs(np.array()-np.array())

order_o10 = 11
func_o10 = uf.chebychev_pol(order_o10)
num_nodes_o10 = 20
############################################

############################################
nodes_o10 = uf.select_node(num_nodes_o10, grid)
para_o10 = uf.find_theta_cheb(Px[0],nodes_o10,order_o10)
f_til_o10 = lambda x: sum(para_o10[idx]* function(x) for idx, function in enumerate(func_o10))
poly_o10 = f_til_o10(grid)
diff_o10 = np.abs(np.array(Px_0)-np.array(poly_o10))
ax.plot(grid, poly_o10, color='gold', label='poly_o10')
ax_diff.plot(grid, diff_o10, color='gold', label='diff_o10')
################################################
nodes1_o10 = uf.select_node(num_nodes_o10, grid)
para1_o10 = uf.find_theta_cheb(Px[1],nodes1_o10,order_o10)
f_til1_o10 = lambda x: sum(para1_o10[idx]* function(x) for idx, function in enumerate(func_o10))
poly1_o10 = f_til1_o10(grid)
diff1_o10 = np.abs(np.array(Px_1)-np.array(poly1_o10))
ax1.plot(grid, poly1_o10, color='gold', label='poly_o10')
ax1_diff.plot(grid, diff1_o10, color='gold', label='diff_o10')

##########################
g3, alx3 = plt.subplots(1,1)
g3.set_figheight(5)
g3.set_figwidth(10)
alx3.plot(grid, poly_o10, color='r', label='rho1=5')
alx3.plot(grid, poly1_o10, color='b', label='rho1=4')
alx3.set_xlabel('x')
alx3.set_ylabel('f(x)')
alx3.set_title('Chebyshev order 10 polynomial: 2 cases')

alx1.legend(loc = 'upper right')
alx2.legend(loc = 'upper right')
alx3.legend(loc = 'upper right')

ax_diff.legend(loc = 'upper right')
ax_diff.set_xlabel('x')
ax_diff.set_ylabel('f(x)')

ax1_diff.legend(loc = 'upper right')
ax1_diff.set_xlabel('x')
ax1_diff.set_ylabel('f(x)')

ax.legend(loc='upper right')
ax1.legend(loc='upper right')


import numpy as np

def pow_iter(A, x_0, tol=10**(-16), max_iter=100):
    y = None
    xo = x_0.copy()
    lamdao = 1
    diff = 10000
    lamdan = 0
    while diff > tol:
        y = np.dot(A, xo)
        xn = y / np.linalg.norm(y, ord=np.inf)
        lamdan = np.linalg.norm(y, ord=np.inf)
        diff = np.abs(lamdao - lamdan) / np.abs(lamdao)
        lamdao = lamdan
        xo = xn
    return xn, lamdao

def main():
	A = np.array([[2, 3, 2], [10, 3, 4], [3, 6, 1]])
	x_0 = np.array([0, 0, 1])
	x, lamda = pow_iter(A.copy(), x_0)
	print("Absolute Value of Largest Eigenvalue:", lamda)
	print("Normalized Eigenvector:", x)

if __name__ == '__main__':
	main()


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sat Jul 10 12:19:07 2021

@author: alessandro
"""

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

def lagrange(x, k):
    if k == 0:
        zeri = x[1:]
    else:
        zeri = np.append(x[:k], x[k+1:])
    n = np.poly(zeri)
    d = np.polyval(n, x[k])
    return n / d

def interpola(x, y, punti):
    n, m = x.size, punti.size
    L = np.zeros((n, m))
    for k in range(n):
        pol = lagrange(x, k)
        L[k, :] = np.polyval(pol, punti)

    return np.dot(y, L)

def f(x): return np.cos(math.pi * x) + np.sin(math.pi * x)
a = 0
b = 2

nodi = np.array([1, 1.5, 1.75])
fnodi = f(nodi)

x = np.linspace(a, b, 100)
y = interpola(nodi, fnodi, x)
plt.plot(nodi, fnodi, 'o')
plt.plot(x, f(x), label="f(x)")
plt.plot(x, y, label="p(x)")
plt.legend()
plt.show()

def p(x): return interpola(nodi, fnodi, np.array([x]))
def r(x): return abs(p(x) - f(x))

x0 = 0.75
rx0 = r(x0)
print(rx0)

nodi = np.array([0.75, 1, 1.5, 1.75])
fnodi = f(nodi)

x = np.linspace(a, b, 100)
y = interpola(nodi, fnodi, x)
plt.plot(nodi, fnodi, 'o')
plt.plot(x, f(x), label="f(x)")
plt.plot(x, y, label="p(x)")
plt.legend()
plt.show()


import scipy.stats
import numpy as np

def g_test(data_counts, expected_counts, ddof: int = 1):
    """Chi-squared test for goodness of fit using likelihood ratio statistic."""
    return chi_squared_goodness_of_fit(
        data_counts, expected_counts, ddof, statistic="llikelihood_ratio"
    )

def chi_squared_goodness_of_fit(
    data_counts, expected_counts, ddof: int = 1, statistic: str = "likelihood_ratio"
):
    """Chi-squared test for goodness of fit.

    Checks whether a given count matches the expected counts from some
    known distribution.

    Assumptions:
        None.

    Test statistic:
        If statistic=`likelihood_ratio`, G = 2 * dot(O, log(O / E))
        If statistic=`pearson_chi_square`, X^{2} = sum((O - E)^2 / E)
    Where:
        `O` is the data_counts;
        `E` is the expected_counts;
        log is the natural log.

    Null distribution: G ~ Chi^2(df) and X^{2} ~ Chi^2(df), where Chi^2
        is the Chi^2 distribution. Also, G is approximately X^{2} under
        the null hypothesis, and usually df = data_bins - 1, but may vary
        depending on the problem.

    H0: the data distribution matches the expected distribution.
    HA: the data distribution follows another latent distribution.
    """
    assert statistic in {"likelihood_ratio", "pearson_chi_square"}

    if statistic == "likelihood_ratio":
        test_statistic = 2.0 * np.dot(
            data_counts, np.log(1e-8 + data_counts / expected_counts)
        )

    else:
        test_statistic = np.sum(
            np.square(data_counts - expected_counts) / expected_counts
        )

    null_dist = scipy.stats.chi2(len(data_counts) - ddof)
    p_value = null_dist.sf(test_statistic)

    return test_statistic, p_value

def _test():
    tosses = 140
    p = 0.85
    x = np.arange(p * tosses - 4, p * tosses + 5)
    expected_counts = tosses * scipy.stats.binom(tosses, p).pmf(x)
    data_counts = np.ceil(
        np.maximum(
            0, expected_counts + np.random.randint(-3, 4, size=expected_counts.size)
        )
    )
    print(data_counts)
    print(expected_counts)

    res = chi_squared_goodness_of_fit(
        data_counts, expected_counts, statistic="likelihood_ratio"
    )
    print(res)

    res = chi_squared_goodness_of_fit(
        data_counts, expected_counts, statistic="pearson_chi_square"
    )
    print(res)
    assert np.allclose(res, scipy.stats.chisquare(data_counts, expected_counts))

if __name__ == "__main__":
    _test()


"""Mulitple linear regression implementation.

Author: Karol Oleszek 2019

Prediction formula:
Y = a + b1 * x1 + b2 * x2 + ... + bn * xn

Observations:
Y = [y1, y2, ..., yn]^t

Explanation variables:
     __               __
    | 1 x11 x12 ... x1k \
    | 1 x21 x22 ... x2k |
x = | .  .   .       .  |
    | .  .   .       .  |
    | 1 xn1 xn2 ... xnk |
    L_                __|

Model parameters:
B = [b1, b2, ..., bn]^t

Model errors:
E = [e1, e2, ..., en]^t

Model estimation:
Y^ = XB^
Y - Y^ = E

Least square estimator of parameters:
B^ = (X^t X)^-1 X^t y
"""

import numpy as np

class MultipleLinearRegressionModel:
    def __init__(self, x, y):
        self.X = np.hstack((np.ones(len(x)).reshape(len(x), 1), np.array(x)))
        self.Y = np.array(y)
        self.B = np.zeros(len(x)).reshape(len(x), 1)
        self.estimations = np.zeros(len(x)).reshape(len(x), 1)
        self.errors = np.zeros(len(x)).reshape(len(x), 1)

    def fit(self):
        print("Fitting model...")
        self.B = np.dot(np.dot(np.linalg.inv(np.dot(self.X.transpose(), self.X)), self.X.transpose()), self.Y)
        print("Estimated model parameters:")
        print(self.B)
        print("Assessing model...")
        self.estimations = np.dot(self.X, self.B)
        self.errors = self.Y - self.estimations
        print("Real values:")
        print(self.Y)
        print("Estimations:")
        print(self.estimations)
        print("Model errors:")
        print(self.errors)
        ssr = sum((self.estimations - np.mean(self.Y)) ** 2)
        ssres = sum((self.Y - self.estimations) ** 2)
        sst = sum((self.Y - np.mean(self.Y)) ** 2)
        F = (ssr / len(self.B)) / (ssres / (len(self.X) - len(self.B) - 1))
        print("F: {0}".format(F))
        rradj = 1 - ((ssr / (len(self.X) - len(self.B) - 1)) / (sst / (len(self.X) - 1)))
        print("R^2 adjusted: {0}".format(rradj))

    def predict(self, x):
        return np.dot(self.B[1:], np.array(x)) + self.B[0]

if __name__ == "__main__":
    mlrm = MultipleLinearRegressionModel([[1, 7], [2, 3], [3, 4], [3, 12], [12, 234]], [1, 2, 3, 3, 12])
    mlrm.fit()
    print("Making predictions:")
    print("x, prediction, error")
    for x in range(12):
        print(x, mlrm.predict([x, 0]), x - mlrm.predict([x, 0]))


"""
Problem Statement

identity

The identity tool returns an identity array. An identity array is a square
matrix with all the main diagonal elements as 1 and the rest as 0. The
default type of elements is float.

import numpy
print numpy.identity(3) #3 is for  dimension 3 X 3

#Output
[[ 1.  0.  0.]
 [ 0.  1.  0.]
 [ 0.  0.  1.]]
eye

The eye tool returns a 2-D array with 1's as the diagonal and 0's elsewhere.
The diagonal can be main, upper or lower depending on the optional parameter
k. A positive k is for the upper diagonal, a negative k is for the lower,
and a 0 k (default) is for the main diagonal.

import numpy
print numpy.eye(8, 7, k = 1)    # 8 X 7 Dimensional array with first upper
diagonal 1.

#Output
[[ 0.  1.  0.  0.  0.  0.  0.]
 [ 0.  0.  1.  0.  0.  0.  0.]
 [ 0.  0.  0.  1.  0.  0.  0.]
 [ 0.  0.  0.  0.  1.  0.  0.]
 [ 0.  0.  0.  0.  0.  1.  0.]
 [ 0.  0.  0.  0.  0.  0.  1.]
 [ 0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.]]

print numpy.eye(8, 7, k = -2)   # 8 X 7 Dimensional array with second lower
diagonal 1.
Task

Your task is to print an array of size NXM with its main diagonal elements
as 1's and 0's everywhere else.

Input Format

A single line containing the space separated values of N and M.
N denotes the rows.
M denotes the columns.

Output Format

Print the desired NXM array.

Sample Input

3 3
Sample Output

[[ 1.  0.  0.]
 [ 0.  1.  0.]
 [ 0.  0.  1.]]
"""
import numpy

n, m = map(int, (raw_input().split()))
print numpy.eye(n, m)