import numpy as np
from scipy import stats

#################
# BSM模型相关
def get_option_d(s, k, t, r, sigma, q):
    d1 = (np.log(s/k) + (r - q + 0.5*sigma**2)*t)/(sigma*np.sqrt(t))
    d2 = (np.log(s/k) + (r - q - 0.5*sigma**2)*t)/(sigma*np.sqrt(t))
    return d1, d2

def get_option_greeks(cp, s, k, t, r, sigma, q):
    """
    计算期权希腊值
    :param cp:
    :param s:
    :param k:
    :param t:
    :param r:
    :param sigma:
    :param q:
    :return:
    """
    d1, d2 = get_option_d(s, k, t, r, sigma, q)
    delta = cp * stats.norm.cdf(cp * d1)
    gamma = stats.norm.pdf(d1) / (s * sigma * np.sqrt(t))
    vega = (s * stats.norm.pdf(d1) * np.sqrt(t))
    theta = (-1 * (s * stats.norm.pdf(d1) * sigma) / (2 * np.sqrt(t)) - cp * r * k * np.exp(-r * t) * stats.norm.cdf(cp * d2))
    return delta, gamma, vega, theta

def bsm_value(cp, s, k, t, r, sigma, q):
    d1, d2 = get_option_d(s, k, t, r, sigma, q)
    if cp > 0:
        value = (
            s*np.exp(-q*t)*stats.norm.cdf(d1) -
            k*np.exp(-r*t)*stats.norm.cdf(d2)
        )
    else:
        value = (
            k * np.exp(-r * t) * stats.norm.cdf(-d2) -
            s*np.exp(-q*t) * stats.norm.cdf(-d1)
        )
    return value
##############

# 二分法迭代计算隐波
def calculate_single_option_iv_by_bsm(
    cp, s, k, c, t, r, q,
    initial_iv=0.5, # 迭代起始值，如果上一个分钟有计算过隐波，这里把上一分钟的结果输入进来，有助于加快收敛
):

    c_est = 0  # 期权价格估计值
    top = 1  # 波动率上限
    floor = 0  # 波动率下限
    sigma = initial_iv  # 波动率初始值
    count = 0  # 计数器
    best_result = 0
    error = abs(c - c_est)
    last_error = error
    while error > 0.0001:
        c_est = bsm_value(cp, s, k, t, r, sigma, q)
        error = abs(c - c_est)
        if error < last_error:
            best_result = sigma

        # 根据价格判断波动率是被低估还是高估，并对波动率做修正
        count += 1
        if count > 100:  # 时间价值为0的期权是算不出隐含波动率的，因此迭代到一定次数就不再迭代了
            sigma = 0
            break

        if c - c_est > 0:  # f(x)>0
            floor = sigma
            sigma = (sigma + top)/2
        else:
            top = sigma
            sigma = (sigma + floor)/2
    return best_result

# 计算隐含分红率
# 我们目前不计算这个
def calculate_dividend_rate(
    underlying_price,    # 当前标的价格
    call_price,
    put_price,
    rest_days,           # 剩余时间
    exercise_price,        # 行权价
    free_rate,
    ):
    c = call_price
    c_p = put_price
    r = free_rate
    t = rest_days / 360
    k = exercise_price
    s = underlying_price
    q = -np.log((c+k*np.exp(-r*t)-c_p)/(s))/t
    return q

# 计算隐波和Greeks
def calculate_single_option_greeks(
    underlying_price,    # 当前标的价格
    option_price,        # 期权价格
    call_put,            # 期权方向, CALL=1 PUT=-1
    rest_days,           # 剩余时间，按自然日计算，也可以用小数来表示不完整的日子
    exercise_price,      # 行权价
    free_rate = 0.03,    # 无风险利率，如果没有数据，指定为3%
    dividend_rate = 0,   # 分红率，目前指定为0
    initial_iv = 0.5,    # 初始迭代的隐波
):
    cp = call_put
    s = underlying_price
    r = free_rate
    k = exercise_price
    t = rest_days / 360
    c = option_price
    q = dividend_rate
    sigma = calculate_single_option_iv_by_bsm(cp, s, k, c, t, r, q, initial_iv)
    delta, gamma, vega, theta = get_option_greeks(cp, s, k, t, r, sigma, q)
    # sigma就是iv
    return sigma, delta, gamma, vega, theta


#! /usr/bin/python
# -*- coding: utf-8 -*-
from __future__ import division
import math
import numpy as np

def homogeneity(m):
    # m sense distribution matrix.
    # rows are clusters, columns are gold stardard.
    nrow, ncol = m.shape
    N = m.sum()

    # conditional part
    conditional_entropy = .0
    for i in xrange(nrow):
        for j in xrange(ncol):
            val = m[i,j]
            if val != 0:
                conditional_entropy -= (val / N) * math.log(val / m[i].sum())

    # total part
    total_entropy = .0
    for i in xrange(ncol):
        val = m.T[i].sum()
        if val != 0:
            total_entropy -= (val / N) * math.log(val / N)

    return 1 - (conditional_entropy / total_entropy)

def completeness(m):
    return homogeneity(m.T)

def vmeasure(m):
    h = homogeneity(m)
    c = completeness(m)
    return (2 * h * c) / (h + c)

def example():
    #m = np.matrix([[10, 10, 15],[20, 50, 0], [1, 10, 60], [5, 0, 0]])
    m = np.matrix([[20, 5, 3],[5, 50, 0], [1, 7, 60], [5, 0, 0]])
    print "Contingency Matrix:\n {}".format(m)
    print "-" * 50
    print "Homogeneity={:.3f}, Completeness={:.3f}, and V-Measure={:.3f}".format(homogeneity(m), completeness(m), vmeasure(m))

if __name__ == '__main__':
    example()


'''
620031587
Net-Centric Computing Assignment
Part A - RSA Encryption

Adapted by Donn Morrison for Python for Programmers IFUD1056-IINI4014
March 2018
donn.morrison@ntnu.no
'''

import random
import numpy as np
from random import randint
import sys

'''
Euclid's algorithm for determining the greatest common divisor
Use iteration to make it faster for larger integers
'''
def gcd(a, b):
    while b != 0:
        a, b = b, a % b
    return a

'''
Euclid's extended algorithm for finding the multiplicative inverse of two numbers
'''
def multiplicative_inverse(a, b):
    """Returns a tuple (r, i, j) such that r = gcd(a, b) = ia + jb
    """
    # r = gcd(a,b) i = multiplicitive inverse of a mod b
    #      or      j = multiplicitive inverse of b mod a
    # Neg return values for i or j are made positive mod b or a respectively
    # Iterateive Version is faster and uses much less stack space
    x = 0
    y = 1
    lx = 1
    ly = 0
    oa = a  # Remember original a/b to remove
    ob = b  # negative values from return results
    while b != 0:
        q = a // b
        (a, b) = (b, a % b)
        (x, lx) = ((lx - (q * x)), x)
        (y, ly) = ((ly - (q * y)), y)
    if lx < 0:
        lx += ob  # If neg wrap modulo orignal b
    if ly < 0:
        ly += oa  # If neg wrap modulo orignal a
    # return a , lx, ly  # Return only positive values
    return lx

def generate_keypair():
    # Generate primes
    primes = PrimeGen(100)
    p = q = 2
    # Select two primes
    while p == q:
        q = primes[randint(0, len(primes)-1)]
        p = primes[randint(0, len(primes)-1)]
    #n = pq
    n = p * q

    #Phi is the totient of n
    phi = (p-1) * (q-1)

    #Choose an integer e such that e and phi(n) are coprime
    e = random.randrange(1, phi)

    #Use Euclid's Algorithm to verify that e and phi(n) are comprime
    g = gcd(e, phi)
    while g != 1:
        e = random.randrange(1, phi)
        g = gcd(e, phi)

    #Use Extended Euclid's Algorithm to generate the private key
    d = multiplicative_inverse(e, phi)

    #Return public and private keypair
    #Public key is (e, n) and private key is (d, n)
    return ((e, n), (d, n))

def encrypt(pk, plaintext):
    #Unpack the key into it's components
    key, n = pk
    #Convert each letter in the plaintext to numbers based on the character using a^b mod m
    cipher = [pow(ord(char), key) % n for char in plaintext]
    #Return the array of bytes
    return cipher

def decrypt(pk, ciphertext):
    #Unpack the key into its components
    key, n = pk
    #Generate the plaintext based on the ciphertext and key using a^b mod m
    plain = [chr(pow(char, key) % n) for char in ciphertext]
    #Return the array of bytes as a string
    return ''.join(plain)

def PrimeGen(n=10000):
    primes = []
    chk = 2
    while len(primes) < n:
        ptest = [chk for i in range(2,chk) if chk%i == 0]
        primes += [] if ptest else [chk]
        chk += 1
    return primes

if __name__ == '__main__':
    if len(sys.argv) < 2:
        print("usage: python rsa.py \"<message>\"")
        sys.exit(1)

    message = sys.argv[1]

    public, private = generate_keypair()

    print("Public key: ", public)
    print("Private key: ", private)

    encrypted_msg = encrypt(public, message)
    print("Your encrypted message is: ")
    print(''.join(map(lambda x: str(x)+ " ", encrypted_msg)))
    print("Your message is:")
    print(decrypt(private, encrypted_msg))


import modelling_functions as mf
import pandas as pd
import numpy as np
from sklearn.decomposition import PCA
from sklearn.manifold import TSNE

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

def plotNewDimension(df):
	components = list(df)
	fig = plt.figure()
	ax = fig.add_subplot(111)
	ax.set_title('Dimension reduction')
	ax.scatter(df[components[0]], df[components[1]])
	ax.set_xlabel('component 1')
	ax.set_ylabel('component 2')

def plotvariables(df,x,y,z):
	fig = plt.figure()
	ax = fig.add_subplot(111, projection='3d')
	ax.scatter(df[x], df[y], df[z], marker='o')
	title1 = ('3d variables')
	ax.set_title(title1,fontsize=7)
	ax.set_xlabel(x)
	ax.set_ylabel(y)
	ax.set_zlabel(z)

df_train = mf.readCSV('train_test_sets/train_set.csv')
x = 'temperature'
y = 'o3'
z = 'humidity'
#df_train = df_train[[x,y,z]]
#PCA
pca = PCA(n_components = 2)
pca.fit(df_train)
pca_train = pca.transform(df_train)
n_samples = df_train.shape[0]

df_pca = pd.DataFrame(data = pca_train,
					  columns = ['pc1', 'pc2'],
					  index = df_train.index)
#TSNE

tsne = TSNE(n_components=2, verbose=1, n_iter=1000, perplexity=35)
tsne_train = tsne.fit_transform(df_train)
df_tsne = pd.DataFrame(data = tsne_train,
					  columns = ['pc1', 'pc2'],
					  index = df_train.index)

#plotvariables(df_train,x,y,z)
plotNewDimension(df_tsne)
plt.show()

Data Preparation Layer/Data Enchichment_ML prep_Outlier Detection module/pca_example.py


import streamlit as st
import sys
import plotly.express as px
import plotly.graph_objs as go
import numpy as np
import pandas as pd

sys.path.append('')
sys.path.append('../../..')

from src.tasks.task3_1_reverse_interpolation.preparation import select_appropriate_points
from src.common.streamlit import function_input
from src.common.processes.find_roots import find_roots
from src.common.func import Func
from src.common.processes.function_nodes import df_from_points
from src.common.segment import Segment
from src.common.point import Point2D
from src.tasks.task2_interpolation.interpolators.newton_interpolator import NewtonInterpolator, \
    ReusableNewtonInterpolator

DEFAULT_FUNCTION = 'cos(x) + 2*x'

st.write("""
# Обратная интерполяция. Вариант 10
""")

with st.form(key='func_form'):
    f, f_lambda = function_input(DEFAULT_FUNCTION)
    a, b = st.slider('[a, b]', -5.0, 5.0, (0.5, 1.8), step=0.1)
    n = st.number_input('Number of nodes', min_value=10, max_value=100)
    submit_button = st.form_submit_button(label='Submit')

domain = Segment(a, b)
f = Func.from_sympy_expr(f, Segment(a, b))

xs = domain.evenly_divide_into_nodes(n)
points = f.calculate_points(xs)

df_points = df_from_points(points).rename(columns={'y': 'f(x)'})

fig = px.line(df_points, x="x", y="f(x)", text="x")
fig.update_traces(textposition="bottom right")

st.plotly_chart(fig)

st.dataframe(df_points.transpose())

with st.form(key='F'):
    F = st.number_input('F =', value=2.4, format='%.4f')
    st.write("We will find x such that f(x) = F.")
    st.form_submit_button(label='Submit')

st.write("""
## Method 1. Inverse function

Suppose the inverse is defined
""")

df1 = df_points.copy().rename(columns={'x': 'f^-1(F)', 'f(x)': 'F'})
df1 = df1[['F', 'f^-1(F)']].copy()
df1_distance = df1.copy()
df1_distance['distance'] = df1_distance['F'].apply(lambda this_F: abs(this_F - F))
sorted_nodes = df1_distance.sort_values(by='distance').reset_index(drop=True)

st.dataframe(sorted_nodes.transpose())

with st.form('degree'):
    degree = st.number_input('Polynomial degree', min_value=1, max_value=(n - 1))
    st.form_submit_button(label='Submit')

selected_nodes_df = sorted_nodes.iloc[:degree + 1]

st.write("Selected nodes")
selected_nodes = selected_nodes_df[['F', 'f^-1(F)']].apply(lambda row: Point2D(row[0], row[1]), axis=1).to_list()

st.write(selected_nodes)

st.write("**Results with Newton Interpolator**")

interpolator = ReusableNewtonInterpolator(selected_nodes)
approx_x = interpolator.calc_approximate_value(F)
st.write(f"Approx. value: {approx_x}")
st.write(f"Absolute error: {abs(f.f(approx_x) - F)}")

dfff1 = pd.DataFrame(columns=['x', 'f(x)'])
dfff1['f(x)'] = np.arange(points[0].y, points[-1].y, 0.01)
dfff1['x'] = dfff1['f(x)'].apply(lambda y: interpolator.calc_approximate_value(y))
dfff1 = dfff1.sort_values(by='x')
dfff1['legend'] = 'Interpolated'

fig = px.line(dfff1[(a <= dfff1.x) & (dfff1.x <= b)], x="x", y="f(x)", color='legend')
fig.add_trace(go.Scatter(x=[approx_x], y=[f.f(approx_x)], name="Approx x"))
st.plotly_chart(fig)

st.write("""
## Method 2. Interpolate then find roots
""")

st.write("All nodes")
st.write(df_points.transpose())

with st.form('method2'):
    degree2 = st.number_input('Polynomial degree', min_value=1, max_value=(n - 1))
    epsilon = st.number_input('Epsilon', min_value=0.0000000000000001, max_value=1.0, value=0.001, step=0.000000000001,
                              format='%.15f')
    st.form_submit_button(label='Submit')

selected_points2 = select_appropriate_points(points, degree2 + 1, F)
st.write("Selected points")
st.write(selected_points2)

interpolator2 = ReusableNewtonInterpolator(selected_points2)

interesting_function = Func(lambda x: interpolator2.calc_approximate_value(x) - F, None, domain)
roots = find_roots(interesting_function, epsilon=epsilon)

st.write("**Roots**")

for i, root in enumerate(roots):
    st.write(f"*{i + 1})*")
    st.write(f"Approx. value: {root}")
    st.write(f"Absolute error: {abs(f.f(root) - F)}")

st.write("**Interpolation result:**")

# Graph the interpolated polynomial
graph_points = df_from_points([Point2D(x, interpolator2.calc_approximate_value(x)) for x in np.arange(a, b, 0.01)])
graph_points['legend'] = 'Interpolated'
fig = px.line(graph_points, x="x", y="y", color='legend')
fig.update_traces(textposition="bottom right")
fig.add_trace(go.Scatter(x=roots, y=[f.f(root) for root in roots], name="Approx x"))
st.plotly_chart(fig)


# coding: utf-8

# In[ ]:

import numpy as np
import matplotlib.pyplot as plt

normal_samples = np.random.normal(size = 100000) # 生成 100000 組標準常態分配（平均值為 0，標準差為 1 的常態分配）隨機變數
uniform_samples = np.random.uniform(size = 100000) # 生成 100000 組介於 0 與 1 之間均勻分配隨機變數

plt.hist(normal_samples)
plt.show()
plt.hist(uniform_samples)
plt.show()

# In[ ]:

import matplotlib.pyplot as plt

speed = [4, 4, 7, 7, 8, 9, 10, 10, 10, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 16, 16, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 20, 20, 20, 20, 20, 22, 23, 24, 24, 24, 24, 25]
dist = [2, 10, 4, 22, 16, 10, 18, 26, 34, 17, 28, 14, 20, 24, 28, 26, 34, 34, 46, 26, 36, 60, 80, 20, 26, 54, 32, 40, 32, 40, 50, 42, 56, 76, 84, 36, 46, 68, 32, 48, 52, 56, 64, 66, 54, 70, 92, 93, 120, 85]

plt.scatter(speed, dist)
plt.show()

# In[3]:

import matplotlib.pyplot as plt

speed = [4, 4, 7, 7, 8, 9, 10, 10, 10, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 16, 16, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 20, 20, 20, 20, 20, 22, 23, 24, 24, 24, 24, 25]
dist = [2, 10, 4, 22, 16, 10, 18, 26, 34, 17, 28, 14, 20, 24, 28, 26, 34, 34, 46, 26, 36, 60, 80, 20, 26, 54, 32, 40, 32, 40, 50, 42, 56, 76, 84, 36, 46, 68, 32, 48, 52, 56, 64, 66, 54, 70, 92, 93, 120, 85]

plt.plot(speed, dist)
plt.show()

# In[8]:

from collections import Counter
import matplotlib.pyplot as plt
import numpy as np

cyl = [6 ,6 ,4 ,6 ,8 ,6 ,8 ,4 ,4 ,6 ,6 ,8 ,8 ,8 ,8 ,8 ,8 ,4 ,4 ,4 ,4 ,8 ,8 ,8 ,8 ,4 ,4 ,4 ,8 ,6 ,8 ,4]

labels, values = zip(*Counter(cyl).items())
width = 1

plt.bar(labels, values)
plt.xticks(values+width * 0.5, labels)
plt.show()

# In[9]:

import numpy as np
import matplotlib.pyplot as plt

normal_samples = np.random.normal(size = 100000) # 生成 100000 組標準常態分配（平均值為 0，標準差為 1 的常態分配）隨機變數

plt.boxplot(normal_samples)
plt.show()

# In[10]:

import numpy as np
import matplotlib.pyplot as plt

normal_samples = np.random.normal(size = 100000) # 生成 100000 組標準常態分配（平均值為 0，標準差為 1 的常態分配）隨機變數

plt.hist(normal_samples)
plt.savefig(filename = "my_hist.png", format = "png")

# In[ ]:


import torch
import numpy as np

def gcd(a, b):
    """Greatest common divisor."""
    a, b = (a, b) if a >=b else (b, a)
    if a%b == 0:
        return b
    else :
        return gcd(b, a%b)

def lcm(a, b):
    """Least common multiple"""
    return a * b // gcd(a, b)

def get_mask_from_lengths(lengths, max_len=None):
    if max_len is None:
        max_len = torch.max(lengths).item()
    ids = torch.arange(0, max_len, out=torch.cuda.LongTensor(max_len))
    mask = (ids < lengths.unsqueeze(1)).bool()
    return mask


import tqdm

from IMLearn.learners import UnivariateGaussian, MultivariateGaussian
import numpy as np
import plotly.graph_objects as go
import plotly.io as pio

pio.templates.default = "simple_white"

def test_univariate_gaussian():
    real_mu, real_var = 10, 1
    samples = np.random.normal(10, 1, 1000)
    uni_g = UnivariateGaussian()
    # Question 1 - Draw samples and print fitted model
    uni_g.fit(samples)
    print(f"({uni_g.mu_}, {uni_g.var_})")

    # Question 2 - Empirically showing sample mean is consistent
    x = []
    y = []
    for i in range(10, 1010, 10):
        x.append(i)
        uni_g.fit(samples[:i])  # get only i samples and fit them
        y.append(np.abs(uni_g.mu_ - real_mu))
    go.Figure(go.Scatter(x=x, y=y, mode='markers+lines',
                         name=r'$\widehat\mu$'),
              layout=go.Layout(
                  title=r"$\text{Q2 Particle section - mean's empirical "
                        r"properties are consistent}$",
                  xaxis_title="$m\\text{ - number of samples}$",
                  yaxis_title="$\widehat\mu\\text{ - absolute distance "
                              "between means}$")).show()

    # Question 3 - Plotting Empirical PDF of fitted model
    pdf_vals = uni_g.pdf(samples)
    go.Figure(go.Scatter(x=samples, y=pdf_vals, mode='markers',
                         name=r'$\widehat\mu$'),
              layout=go.Layout(
                  title=r"$\text{Q3 Particle section - Empirical PDF of "
                        r"fitted model}$",
                  xaxis_title="$\\text{Samples}$",
                  yaxis_title="$PDF values$")).show()

def test_multivariate_gaussian():
    # Question 4 - Draw samples and print fitted model
    mu = np.array([0, 0, 4, 0])
    Sigma = np.array([[1, 0.2, 0, 0.5],
                      [0.2, 2, 0, 0],
                      [0, 0, 1, 0],
                      [0.5, 0, 0, 1]])
    samples = np.random.multivariate_normal(mu, Sigma, 1000)
    mg = MultivariateGaussian()
    mg.fit(samples)
    # prints values.
    print(mg.mu_)
    print(mg.cov_)

    # Question 5 - Likelihood evaluation
    f_arr = np.linspace(-10, 10, 200)
    # results matrix, which is 200x200
    log_l_vals = np.ndarray(shape=(len(f_arr), len(f_arr)))
    for i in range(len(f_arr)):
        for j in range(len(f_arr)):
            new_mu = np.array([f_arr[i], 0, f_arr[j], 0])
            log_l_vals[i][j] = mg.log_likelihood(new_mu, Sigma, samples)
    # matrix was transposed to align the correct x,y values in the heatmap
    go.Figure(go.Heatmap(x=f_arr, y=f_arr, z=np.transpose(log_l_vals)),
              layout=go.Layout(
        title=r"$\text{Q5 Particle section - Log Likelihood Heatmap}$",
        xaxis_title="$f1\\ values$",
        yaxis_title="$f2\\ values$")).show()

    # Question 6 - Maximum likelihood
    maxarg_model_ind = np.where(log_l_vals == np.amax(log_l_vals))
    # wasn't instructed to print the values, but may easily be carried out.
    maxargs = (f_arr[maxarg_model_ind[0][0]], f_arr[maxarg_model_ind[1][0]])

if __name__ == '__main__':
    np.random.seed(0)
    test_univariate_gaussian()
    test_multivariate_gaussian()


# All basic usage of numpy
import numpy as np
# prints the version of numpy
print(np.__version__)

# Whether element is a numpy array
el = np.array(list())
# Below command resolves to true
if isinstance(el, np.ndarray):
    print("Element is a numpy array.")

array1 = np.array([1, 2, 3, 4])
# It performs element wise operation on whole collection
sum_of_array = array1 + array1
# Returns [2, 4, 6, 8]
print(sum_of_array)

# We can access individual numpy array elements, use square brackets
# Prints 2. i.e. value of array with index 1
print(array1[1])
# Returns array of boolean values which are greater than 2
array2 = array1 > 2

# Prints [False, False, True, True]
print(array2)
# We can print selective items of array by passing array of boolean values
array3 = array1[array2]
print(array3)

two_d_list = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]
two_d_array = np.array(two_d_list)
# Shape is 3 rows, 4 columns
print(two_d_array.shape)
# To get all the 3rd columns of
print(two_d_array[:,2])
# To get values [6, 7]
print(two_d_array[1,1:3])

# Reshape
org_array = [1, 2, 3, 4, 5, 6, 7, 8]
conv_np_array = np.array(org_array)
# Returns (8,) as shape
print('Shape ', conv_np_array.shape)
# Converting into shape of (2,4)
conv_2_4_array = np.reshape(conv_np_array, [2, 4])
# Returns (2, 4) as shape
print('Shape ', conv_2_4_array.shape)
# Prints [[1 2 3 4], [5 6 7 8]]
print('Element of conv_2_4_array', conv_2_4_array)
# Converting into shape of (2, 2, 2)
conv_2_2_2_array = np.reshape(conv_np_array, [2, 2, 2])
# Returns (2, 2, 2) as shape
print('Shape ', conv_2_2_2_array.shape)
# Prints
"""
[[[1 2]
  [3 4]]

 [[5 6]
  [7 8]]]
"""
print('Element of conv_2_2_2_array', conv_2_2_2_array)

# The shape will convert [row1, row2, ....rown-1, col]
# If we want to have single row with elements just 1 or -1 to the top of the shape list.

# Converting into shape of (1, 2, 2, 2)
conv_1_2_2_2_array = np.reshape(conv_np_array, [-1, 2, 2, 2])
# Returns (1, 2, 2, 2) as shape, even if we gave first dimension of shape as -1
print('Shape ', conv_1_2_2_2_array.shape)
"""
[[[[1 2]
   [3 4]]

  [[5 6]
   [7 8]]]]
"""
print('Element of conv_1_2_2_2_array', conv_1_2_2_2_array)

# Perform an operation on each element of array
"""
import math
import numpy as np

def calcSigmoid(z):
    return 1 / ( 1 + math.exp(-z) )

def sigm(X):
    sm = np.vectorize(calcSigmoid)
    return sm(X)

sigm([1,0])
array([0.73105858, 0.5       ])
"""

# Adding columns

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

sec = np.array([[5],[6]])
'''
array([[5],
       [6]])
'''

# on column concat
third = np.concatenate((first, sec), axis=1)
'''
array([[1, 2, 5],
       [3, 4, 6]])
'''

# Get the scalar value of (1,1) matrix
in_vec = np.array([[5]])
'''
array([[5]])
'''
in_vec.shape # (1, 1)
in_scalar = np.asscalar(in_vec) # 5

# identity matrix
eye = np.eye(3)
'''
array([[1., 0., 0.],
       [0., 1., 0.],
       [0., 0., 1.]])
'''

# Reading csv file
'''
from numpy import genfromtxt
my_data = genfromtxt('my_file.csv', delimiter=',')
'''

'''
X = np.arange(1,7)
#array([1, 2, 3, 4, 5, 6])
X = X.reshape(3, 2)

array([[1, 2],
       [3, 4],
       [5, 6]])

If we see the elements arranged in filling first rows by rows
If we want to fill by columns first, i.e

array([[1, 4],
       [2, 5],
       [3, 6]])

We can do in two ways

1. First take the order in reverse then transpose

X = np.arange(1,7).reshape(2,3) # Observe 2,3 rather thn 3,2
X = X.T

2. Chaining with swapaxes

X = np.arange(1,7).reshape(2,3).swapaxes(0,1)
'''

'''
Indexing from particular index to end
mm = np.arange(1,5).reshape(2,2)
mm
array([[1, 2],
       [3, 4]])
nn = mm.flatten().reshape((4,1))
array([[1],
       [2],
       [3],
       [4]])
# From index 2 to end
nn[2:,]
array([[3],
       [4]])


import torch
import numpy as np

def interval_score_loss(predictions, real, alpha=0.28):
    """
    Taken from: https://stats.stackexchange.com/questions/194660/forecast-accuracy-metric-that-involves-prediction-intervals
    Need to predict lower and upper bounds of interval, use target to assess error.

    :param lower: Lower bound predictions
    :param upper: Upper bound predictions
    :param real: Target
    :param alpha: Alpha in metric in
    :return: Average of interval score loss
    """
    lower = predictions[:, 0]
    upper = predictions[:, 1]

    real_lower = 2 * torch.abs(real - lower) / alpha
    upper_real = 2 * torch.abs(upper - real) / alpha
    upper_lower = torch.abs(upper - lower)

    real_lower[real > lower] = 0
    upper_real[real < upper] = 0

    return torch.sum(real_lower + upper_real + upper_lower) / len(real)

"""Implementation of the quantile loss function"""

from typing import Sequence
import numpy as np

def quantile_loss(
    predictions: Sequence[float], targets: Sequence[float], quantile: float
) -> float:
    """Quantile loss function.

    Args:
        predictions (sequence of floats):
            Model predictions, of shape [n_samples,].
        targets (sequence of floats):
            Target values, of shape [n_samples,].
        quantile (float):
            The quantile we are seeking. Must be between 0 and 1.

    Returns:
        float: The quantile loss.
    """
    # Convert inputs to NumPy arrays
    target_arr = np.asarray(targets)
    prediction_arr = np.asarray(predictions)

    # Compute the residuals
    res = target_arr - prediction_arr

    # Compute the mean quantile loss
    loss = np.mean(
        np.maximum(res, np.zeros_like(res)) * quantile
        + np.maximum(-res, np.zeros_like(res)) * (1 - quantile)
    )

    # Ensure that loss is of type float and return it
    return float(loss)

def smooth_quantile_loss(
    predictions: Sequence[float],
    targets: Sequence[float],
    quantile: float,
    alpha: float = 0.4,
) -> float:
    """The smooth quantile loss function from [1].

    Args:
        predictions (sequence of floats):
            Model predictions, of shape [n_samples,].
        targets (sequence of floats):
            Target values, of shape [n_samples,].
        quantile (float):
            The quantile we are seeking. Must be between 0 and 1.
        alpha (float, optional):
            Smoothing parameter. Defaults to 0.4.

    Returns:
        float: The smooth quantile loss.

    Sources:
        [1]: Songfeng Zheng (2011). Gradient Descent Algorithms for
             Quantile Regression With Smooth Approximation. International
             Journal of Machine Learning and Cybernetics.
    """
    # Convert inputs to NumPy arrays
    target_arr = np.asarray(targets)
    prediction_arr = np.asarray(predictions)

    # Compute the residuals
    residuals = target_arr - prediction_arr

    # Compute the smoothened mean quantile loss
    loss = quantile * residuals + alpha * np.log(1 + np.exp(-residuals / alpha))

    # Ensure that loss is of type float and return it
    return float(loss.mean())


import pandas as pd
from sklearn.preprocessing import scale
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
import numpy as np
from sklearn.decomposition import PCA

filename='kmeans_testing.xlsx'

factor3=pd.read_excel(filename,index_col=0)

# print(factor3.head())

# print(type(factor3))

# factor3 데이터에 대한 군집화 수행 결과가 kmeans 객체 변수로 반환
kmeans=KMeans(n_clusters=4, init='k-means++', max_iter=300, random_state=0).fit(factor3)

# kmeans의 labels_ 속성값을 확인하면 데이터가 어떤 중심에 속하는지 알 수 있음
print(kmeans.labels_)

factor3['cluster']=kmeans.labels_

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

pca=PCA(n_components=2)
pca_transformed=pca.fit_transform(factor3)

factor3['pca_x']=pca_transformed[:,0]
factor3['pca_y']=pca_transformed[:,1]

print(factor3.head())

# 각 클러스터의 인덱스 불러오기
marker0_ind=factor3[factor3['cluster']==0].index
print(marker0_ind)
marker1_ind=factor3[factor3['cluster']==1].index
print(marker1_ind)
marker2_ind=factor3[factor3['cluster']==2].index
print(marker2_ind)
marker3_ind=factor3[factor3['cluster']==3].index
print(marker3_ind)
# marker4_ind=factor3[factor3['cluster']==4].index
# print(marker4_ind)
# 군집 값 0,1,2에 해당하는 인덱스로 각 군집 레벨의 좌표값 추출
plt.scatter(x=factor3.loc[marker0_ind,'pca_x'], y=factor3.loc[marker0_ind,'pca_y'],marker='o') #8 2
plt.scatter(x=factor3.loc[marker1_ind,'pca_x'], y=factor3.loc[marker1_ind,'pca_y'],marker='s') #14 5
plt.scatter(x=factor3.loc[marker2_ind,'pca_x'], y=factor3.loc[marker2_ind,'pca_y'],marker='^') #3 13
plt.scatter(x=factor3.loc[marker3_ind,'pca_x'], y=factor3.loc[marker3_ind,'pca_y'],marker='*') #3 4    9개
# plt.scatter(x=factor3.loc[marker4_ind,'pca_x'], y=factor3.loc[marker4_ind,'pca_y'],marker='4') #3 1  10개
plt.xlabel('PCA1')
plt.ylabel('PCA2')

plt.title('3 Clusters Visualization by 2 PCA Components')
plt.show()

from sklearn.metrics import silhouette_samples,silhouette_score

# 모든 개별 데이터의 실루엣 계수 구함
score_samples=silhouette_samples(factor3,factor3['cluster'])
print('silhouette_samples() return of shape',score_samples.shape)

factor3['silhouette_coeff']=score_samples

# 모든 데이터의 평균 실루엣 계수 값 구함
average_score=silhouette_score(factor3,factor3['cluster'])
print('factor3 data set Silhouette Analysis Score:{0:3f}'.format(average_score))

print(factor3)

filename2='k_means_ana.csv'
factor3.to_csv(filename2,encoding='cp949')
print('fin')


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Tests for label propagation"""

import unittest

from scipy.special import comb

from sknetwork.data import karate_club, edgelist2adjacency
from sknetwork.data.test_graphs import *
from sknetwork.topology import Triangles

class TestTriangleListing(unittest.TestCase):

    def test_empty(self):
        adjacency = test_graph_empty()
        self.assertEqual(Triangles().fit_transform(adjacency), 0)

    def test_disconnected(self):
        adjacency = test_graph_disconnect()
        self.assertEqual(Triangles().fit_transform(adjacency), 1)

    def test_cliques(self):
        adjacency = test_graph_clique()
        n = adjacency.shape[0]
        nb = Triangles().fit_transform(adjacency)
        self.assertEqual(nb, comb(n, 3, exact=True))

    def test_clustering_coeff(self):
        edgelist = [(0, 1), (1, 2), (2, 3), (3, 0), (0, 2)]
        adjacency = edgelist2adjacency(edgelist, undirected=True)

        triangles = Triangles().fit(adjacency)
        self.assertEqual(0.75, triangles.clustering_coef_)

    def test_options(self):
        adjacency = karate_club()

        self.assertEqual(Triangles(parallelize=False).fit_transform(adjacency), 45)
        self.assertEqual(Triangles(parallelize=True).fit_transform(adjacency), 45)


# This script defines and tests a function for generating a sequence of normally
# distributed random numbers using the Box-Muller method.
#
# Ref. 1: Numerical Recipes in C 2nd ed.
# Ref. 2: Statistics for Engineers and Scientists 2nd ed. Navidi
#

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

def gaussian(mu=0, sigma=1):
    """Generate a random number from a Gaussian distribution.

    Adapted from ref 1.
    """

    if "iset" not in gaussian.__dict__:
        gaussian.iset = 0
    if "gset" not in gaussian.__dict__:
        gaussian.gset = 0

    if gaussian.iset == 0:
        v1, v2, rsq = 0.0, 0.0, 0.0
        while rsq >= 1.0 or rsq == 0.0:
            v1 = 2.0*random.random() - 1
            v2 = 2.0*random.random() - 1
            rsq = v1*v1 + v2*v2
        fac = np.sqrt(-2.0*np.log(rsq)/rsq)
        gaussian.iset = 1
        gaussian.gset = v1*fac
        xi = v2*fac
    else:
        gaussian.iset = 0
        xi = gaussian.gset

    return mu + xi*sigma  # See ref 2 pg. 242

def gaussian_distribution(mu=0, sigma=1, n=100):
    """Create a list of random numbers from a Gaussian distribution."""
    return [gaussian(mu, sigma) for _ in range(n)]

if __name__ == "__main__":

    # Test the distribution
    mean = 0
    stddev = 1
    nsamps = 100000
    nbins = int((2*nsamps)**(1./3))

    # Plot theoretical distribution
    pdf_range = np.arange(-6, 6, 0.001)
    pdf = norm.pdf(pdf_range, mean, stddev)

    # Create the histogram of generated values
    x = gaussian_distribution(mu=mean, sigma=stddev, n=nsamps)
    plt.hist(x, bins=nbins, normed=True)
    plt.plot(pdf_range, pdf, linewidth=2, color='r')
    plt.grid(True)
    plt.ylabel("PDF")
    plt.xlabel("Random Values")
    plt.show()


import matplotlib.pyplot as plt
import numpy as np

def rect(x):
    r"""
    Rectangle function:
        rect(x) = {1, if |x|<= 0.5; 0, otherwise}
    """
    return np.where(np.abs(x) >= 0.5, 0, 1)

def chirp(t, T, Kr):
    """
    Create a chirp signal :
        S_{tx}(t) = rect(t/T) * exp(1j*pi*Kr*t^2)
    """
    return rect(t / T) * np.exp(1j * np.pi * Kr * t ** 2)

Ns = 1000
t = np.linspace(-1, 1, Ns)
yrect = rect(t)

plt.figure()
plt.plot(t, yrect, '-r', linewidth=2)
plt.axis([-1, 1, -0.1, 1.1])
plt.grid()
plt.xlabel('Time/s')
plt.ylabel('Amplitude')
plt.title('rect')
plt.show()

Kr1 = 5
Kr2 = 20
T1 = 2.0
T2 = 4.0
t = np.linspace(-3, 3, Ns)
ychirp1 = chirp(t, T1, Kr=Kr1)
ychirp2 = chirp(t, T2, Kr=Kr1)

ychirp3 = chirp(t, T1, Kr=Kr2)
ychirp4 = chirp(t, T2, Kr=Kr2)

plt.figure()
plt.subplot(221)
plt.grid()
plt.plot(t, ychirp1, '-r')
plt.xlabel('Time/s')
plt.ylabel('Amplitude')
plt.title("T=" + str(T1) + "s, K=" + str(Kr1) + "Hz/s")
plt.subplot(222)
plt.grid()
plt.plot(t, ychirp2, '-b')
plt.xlabel('Time/s')
plt.ylabel('Amplitude')
plt.title("T=" + str(T2) + "s, K=" + str(Kr1) + "Hz/s")
plt.subplot(223)
plt.grid()
plt.plot(t, ychirp3, '-r')
plt.xlabel('Time/s')
plt.ylabel('Amplitude')
plt.title("T=" + str(T1) + "s, K=" + str(Kr2) + "Hz/s")
plt.subplot(224)
plt.grid()
plt.plot(t, ychirp4, '-b')
plt.xlabel('Time/s')
plt.ylabel('Amplitude')
plt.title("T=" + str(T2) + "s, K=" + str(Kr2) + "Hz/s")
plt.tight_layout()
plt.show()

# ==================compute spectral

ychirp1_fft = np.fft.fft(ychirp1)
ychirp2_fft = np.fft.fft(ychirp2)
ychirp3_fft = np.fft.fft(ychirp3)
ychirp4_fft = np.fft.fft(ychirp4)

ychirp1_fft = np.fft.fftshift(ychirp1_fft)
ychirp2_fft = np.fft.fftshift(ychirp2_fft)
ychirp3_fft = np.fft.fftshift(ychirp3_fft)
ychirp4_fft = np.fft.fftshift(ychirp4_fft)

f = np.fft.fftfreq(t.shape[-1])
# print(f)
f = np.fft.fftshift(f)
# print(f)

plt.figure()
plt.subplot(221)
plt.grid()
plt.plot(f, np.abs(ychirp1_fft), '-r')
plt.xlabel('Frequency/Hz')
plt.ylabel('Amplitude')
plt.title("T=" + str(T1) + "s, K=" + str(Kr1) + "Hz/s")
plt.subplot(222)
plt.grid()
plt.plot(f, np.abs(ychirp2_fft), '-b')
plt.xlabel('Frequency/Hz')
plt.ylabel('Amplitude')
plt.title("T=" + str(T2) + "s, K=" + str(Kr1) + "Hz/s")
plt.subplot(223)
plt.grid()
plt.plot(f, np.abs(ychirp3_fft), '-r')
plt.xlabel('Frequency/Hz')
plt.ylabel('Amplitude')
plt.title("T=" + str(T1) + "s, K=" + str(Kr2) + "Hz/s")
plt.subplot(224)
plt.grid()
plt.plot(f, np.abs(ychirp4_fft), '-b')
plt.xlabel('Frequency/Hz')
plt.ylabel('Amplitude')
plt.title("T=" + str(T2) + "s, K=" + str(Kr2) + "Hz/s")
plt.tight_layout()
plt.show()


# Polynomial Regression

# Importing the libraries
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

# Importing the dataset
dataset = pd.read_csv('Position_Salaries.csv')
X = dataset.iloc[:, 1:2].values
y = dataset.iloc[:, 2].values

# Splitting the dataset into the Training set and Test set
"""from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 0)"""

# Feature Scaling
"""from sklearn.preprocessing import StandardScaler
sc_X = StandardScaler()
X_train = sc_X.fit_transform(X_train)
X_test = sc_X.transform(X_test)"""

# Fitting Linear Regression to the dataset
from sklearn.linear_model import LinearRegression
lin_reg = LinearRegression()
lin_reg.fit(X, y)

# Fitting Polynomial Regression to the dataset
from sklearn.preprocessing import PolynomialFeatures
poly_reg = PolynomialFeatures(degree = 4)
X_poly = poly_reg.fit_transform(X)
poly_reg.fit(X_poly, y)
lin_reg_2 = LinearRegression()
lin_reg_2.fit(X_poly, y)

# Visualising the Linear Regression results
plt.scatter(X, y, color = 'red')
plt.plot(X, lin_reg.predict(X), color = 'blue')
plt.title('Truth or Bluff (Linear Regression)')
plt.xlabel('Position level')
plt.ylabel('Salary')
plt.show()

# Visualising the Polynomial Regression results
plt.scatter(X, y, color = 'red')
plt.plot(X, lin_reg_2.predict(poly_reg.fit_transform(X)), color = 'blue')
plt.title('Truth or Bluff (Polynomial Regression)')
plt.xlabel('Position level')
plt.ylabel('Salary')
plt.show()

# Visualising the Polynomial Regression results (for higher resolution and smoother curve)
"""
plt.scatter(X, y, color = 'red')
plt.plot(X_grid, lin_reg_2.predict(poly_reg.fit_transform(X_grid)), color = 'blue')
plt.title('Truth or Bluff (Polynomial Regression)')
plt.xlabel('Position level')
plt.ylabel('Salary')
plt.show()

# Predicting a new result with Linear Regression
lin_reg.predict([[6.5]])

# Predicting a new result with Polynomial Regression
lin_reg_2.predict(poly_reg.fit_transform([[6.5]]))
"""


import numpy as np
from sympy import Matrix

class SisLin:

    def __init__(self, A, B = [0, 0, 0]):
        self.A = np.array(A, dtype = float)
        self.B = np.array(B, dtype = float)
        self.L = None
        self.U = None

    def verifyLU(self):
        m, n = self.A.shape
        for i in range(1, m+1):
            print(f'Minimo quadrado da matriz A_{i}{i}: ', np.round(np.linalg.det(self.A[:i,:i]), 4))

    def LU(self):
        U = np.copy(self.A)
        L = np.zeros(np.shape(self.A))
        pivot = []
        m,n = U.shape
        for i in range(n-1):
            for j in range(i+1, n):
                if U[i,i] == 0:
                    print('Existe elemento nulo na diagonal principal!')
                    break
                ml = U[j,i]/U[i,i]
                U[j,:] = U[j,:] - ml*U[i,:]
                pivot.append(ml)

        pivot = np.array(pivot)

        for i in range(n-1):
            for j in range(i+1, n):
                L[j,i] = pivot[0]
                pivot = np.delete(pivot, 0)

        for i in range(n):
            for j in range(n):
                if i == j:
                    L[i,j] = 1
        Ldf = Matrix(L)
        Udf = Matrix(U)
        self.L = L
        self.U = U

        print('*' * 14,'Matriz L', '*' * 14 ,'\n')

        display(Ldf)

        print('*' * 14,'Matriz U', '*' * 14 ,'\n')

        display(Udf)

    def goit(self):
        L = np.copy(self.L)
        B = np.copy(self.B).T
        m, n = self.L.shape
        k = 1
        for i in range(m - 1):
            for j in range(k, n):
                c = L[i][i] / L[j][i]
                L[j] = (L[i] - c * L[j])
                B[j] = (B[i] - c * B[j])
            k += 1

        Y = self.solution(L, B).T
        print('Vetor Y:', Y[0])
        X = self.solution(self.U, Y)
        print('Vetor X:', X.T[0])

        #return X

    def solution(self, l , y):
        L = np.copy(l)
        Y = np.copy(y).T
        m, n = L.shape
        X = np.zeros((1, len(Y))).T
        k = n - 2
        X[len(Y) - 1] = Y[-1] / L[-1][-1]

        for i in range(m-2, -1, -1):
            X[i] = ((Y[i:] - L[i][i+1:].dot(X[i+1:])) / L[i][i])[0]

        return X

    def Jacobi_Richardson(self, e = 0.1, c = 4, X0 = [0, 0, 0], lim = 50, erro = 0):

        error = lambda x1, x2: np.linalg.norm(x1 - x2)
        if erro == 1:
            error = lambda x1, x2: np.max(np.abs(x1- x2))/np.max(np.abs(x1))

        a = np.copy(self.A)
        b = np.copy(self.B).T
        X = np.zeros(b.shape)
        X_aux = np.array(X0, dtype = float)
        m, n = a.shape
        N = 0
        k = 1

        for j in range(m):
            X[j] = b[j] / a[j,j]
            X[j] -= np.sum(np.delete(X_aux, j) * (np.array([np.delete(a[j], j)]) / (a[j,j])))
        print(f'x_{k}: ', np.round(X, c))

        while error(X, X_aux) > e and N < lim:
            X_aux = np.copy(X)
            for j in range(m):
                X[j] = b[j] / a[j,j]
                X[j] -= np.sum(np.delete(X_aux, j) * (np.array([np.delete(a[j], j)]) / (a[j,j])))
            k += 1
            N += 1
            print(f'x_{k}: ', np.round(X, c))

    def verify_JR(self):
        m, n = self.A.shape
        B = []
        for i in range(m):
            B_aux = np.sum(np.absolute(np.delete(self.A[i], i) / self.A[i,i]))
            B.append(B_aux)
            if B_aux >= 1:
                print('Não há garantia de convergencia pelo método de Jacobi-'
                      'Richardson.')
                return print(f'B_{i+1} = {B[i]:.4f}')

        print('Há garantia de convergencia pelo método de Jacobi-Richardson')
        return print('B = ', B)

    def verify_GS(self):
        m, n = self.A.shape
        B = np.ones((1, m))
        for i in range(m):
            B[0][i] = np.sum(np.absolute(np.delete(self.A[i], i) / self.A[i,i] * np.delete(B, i)))
            if B[0][i] >= 1:
                print('Não há garantia de convergencia pelo método de Gauss-'
                      'Seidel.')
                return print(f'B_{i+1} = {B[0][i]:.4f}')
        print('Há garantia de convergencia pelo método de Gauss-Seidel')
        return print(f'B = ', B[0])

    def Gauss_Seidel(self, e = 0.1, c = 4, X0 = [0, 0, 0], lim = 50, erro=0):

        error = lambda x1, x2: np.linalg.norm(x1 - x2)
        if erro == 1:
            error = lambda x1, x2: np.max(np.abs(x1- x2))/np.max(np.abs(x1))

        a = np.copy(self.A)
        b = np.copy(self.B).T
        X = np.array(X0, dtype = float)
        X_ant = np.copy(X)
        m, n = a.shape
        k = 1
        N = 0

        for j in range(m):
            X[j] = b[j] / a[j,j]
            X[j] -= np.sum(np.delete(X, j) * (np.array([np.delete(a[j], j)]) / (a[j,j])))
        print(f'x_{k}: ', np.round(X, c))

        while error(X, X_ant) > e and N < lim:
            X_ant = np.copy(X)
            for j in range(m):
                X[j] = b[j] / a[j,j]
                X[j] -= np.sum(np.delete(X, j) * (np.array([np.delete(a[j], j)]) / (a[j,j])))
            k += 1
            N += 1
            print(f'x_{k}: ', np.round(X, c))


##############################################################################
### Python 2nd Order ODE solver, using the Runge-Kutta 4th order method
### Solves ordinary differential equations of the form
###
###			(d^2)x/(dt^2) = f(t, x, v)
###
### As usual, the 2nd order ODE is split into two coupled 1st order ODEs,
### which are solved with the Runge-Kutta function:
###
###                                     | x'(t) = v(t)
###              x''(t) = f(t, x, v) -> |
###                                     | v'(t) = f(t, x, v)
###
### User must input the following parameters:
### 1. Via command line arguments: time step, total time, output interval.
### 2. The right-hand side of the differential equation
###    inside the rhs function, in the rungekutta2.py file.
### 3. Initial conditions t_0, x_0, v_0 (example: x(t_0) = x_0, v(t_0) = v_0),
###    at the beginning of the code, right below the imports.
###
### The force can be specified inside the "force" function, in rungekutta2.py.
###
### Example: python ODE2.py 0.1 100 10
### This will solve the ODE with a timestep of dt = 0.1, for 100 time units,
### writing output every 10 time steps.
###
### Output: File "RK4_2_output.txt", also plots results.
###
### Author: Nikos Tryfonidis, November 2015
### The MIT License (MIT)
### Copyright (c) 2015 Nikos Tryfonidis
### See LICENSE.txt
##############################################################################

# Import necessary packages
import numpy as np
import sys

# Import functions
from rungekutta2 import RK4_2nd
from plot1D import plot1D

##### Set Initial Conditions Here: #####
t_0 = 0.0
x_0 = 0.0
v_0 = 2.0
########################################

#################################################################################
### Command line arguments:
#################################################################################

# Check number of command line arguments
if len(sys.argv) != 4:
	print "Usage: python ODE2.py <timestep> <total time> <output interval>"
	print "Please run again following the command line input format above."
	print "Exiting..."
	sys.exit(1)

# Get command line arguments
h = float(sys.argv[1])
totalTime = float(sys.argv[2])
interval = int(sys.argv[3])

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

# Calculate number of time steps
totalSteps = totalTime/h
# Find size of output
size = int(totalSteps/interval) + 1

# Print a summary of parameters
print "Running Runge-Kutta with the following parameters:"
print "Time step: %f\tTotal time: %f\t" %(h, totalTime)
print "Output interval: %d" %interval

# Allocate variable arrays and apply given initial conditions
t = np.linspace(t_0, t_0 + totalTime, size)

x = np.zeros(size)
x[0] = x_0

v = np.zeros(size)
v[0] = v_0

# Call Runge Kutta
tOld = t[0]
xOld = x[0]
vOld = v[0]
for i in xrange(1, size):
    for j in xrange(0, interval):
        tOld += h    # Unnecessary, but to keep generality
        xOld, vOld = RK4_2nd(tOld, xOld, vOld, h)
    x[i] = xOld
    v[i] = vOld

# Save t, x and v into output file (each array is a column)
np.savetxt('RK4_2_output.txt', np.c_[t, x, v], fmt='%.10f')

# Plot t, x (plot1d function in plot1D.py)
plot1D(size, "RK4_2_output.txt")


"""Utils related to GSP."""

import numpy as np

def eigendecompose(S):
    """Eigendecompose the input matrix."""
    eigvals, V = np.linalg.eig(S)
    return eigvals, V

def gft(S, x, decompose_shift=True):
    """Perform the inverse GFT.

    Parameters
    ----------
    S : np.ndarray, shape=(N, N)
        Graph shift operator or GFT matrix.
    x : np.ndarray, shape=(N,) or (N, 1)
        Graph signal spectrum.
    decompose_shift : bool, default=True

    Example
    -------
    >>> from gspx.utils.gsp import gft, igft
    >>> from gspx.utils.graph import make_sensor
    >>> A, coords = make_sensor(N=10, seed=2)
    >>> s = np.arange(10)
    >>> s_ = gft(A, igft(A, s))
    >>> np.round(np.sum(s_ - s), decimals=10)
    0.0

    """
    if decompose_shift:
        _, U = eigendecompose(S)
        Uinv = np.linalg.inv(U)
    else:
        Uinv = S.copy()

    not_column = False
    if len(x.shape) == 1:
        x_column = x[:, np.newaxis]
        not_column = True
    else:
        x_column = x.copy()

    out = Uinv @ x_column

    if not_column:
        return out.ravel()
    else:
        return out

def igft(S, x, decompose_shift=True):
    """Perform the inverse GFT.

    Parameters
    ----------
    S : np.ndarray, shape=(N, N)
        Graph shift operator or IGFT matrix.
    x : np.ndarray, shape=(N,) or (N, 1)
        Graph signal spectrum.
    decompose_shift : bool, default=True

    Example
    -------
    >>> from gspx.utils.gsp import gft, igft
    >>> from gspx.utils.graph import make_sensor
    >>> A, coords = make_sensor(N=10, seed=2)
    >>> s = np.arange(10)
    >>> s_ = gft(A, igft(A, s))
    >>> np.round(np.sum(s_ - s), decimals=10)
    0.0

    """
    if decompose_shift:
        _, U = eigendecompose(S)
    else:
        U = S.copy()
    return gft(U, x, decompose_shift=False)


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sat Jun 12 21:46:25 2021

@author: surajitrana
"""

""" Draw a line in a diagram from position
(1, 3) to (2, 8) then to (6, 1) and finally
to position (8, 10):
"""

import matplotlib.pyplot as plt
import numpy as np
def plot_graph():
    x_points = np.array([1, 2, 6, 8])
    y_points = np.array([3, 8, 1, 10])
    plt.plot(x_points, y_points)
    plt.show()

if __name__ == "__main__":
    plot_graph()


import pytest
from autodiff.interface.interface import AutoDiff as AD
import autodiff.admath.admath as admath

import numpy as np

def my_fn_2d(x, y):
	return [x**2 + y**2, x + 2+y]

def my_fn_1d(x,y):
	return x**2 + y**2

def test_list():
	fn = AD(my_fn_1d)
	der = fn.get_der([1,2])
	assert der == [2, 4]

def test_list_lists():
	fn = AD(my_fn_1d)
	der = fn.get_der([[1,2],[3,4],[5,6]])
	assert der == [[2, 4], [6, 8], [10, 12]], [[1, 1], [1, 1], [1, 1]]

def test_2d_fn():
	fn = AD(my_fn_2d, ndim=2)
	der = fn.get_der([1,2])
	assert der == [[2, 4], [1, 1]]

def test_func_w_mult_params_single_var():
	fn = lambda x,y: x**2
	ad_fn = AD(fn)
	der = ad_fn.get_der([1,2])
	assert der == [2, 0]

def square_fn(x):
        return x ** 2

def test_square_fn():
	ad_square = AD(square_fn)
	der = ad_square.get_der(3)
	assert der == 6
	der1 = ad_square.get_der([1,2,3,4])
	assert der1 == [2, 4, 6, 8]

def test_get_der_types():
	with pytest.raises(TypeError):
        	AD.get_der('string')
	with pytest.raises(TypeError):
        	AD.get_der(dict[1:'a', 2:'b'])

def test_get_der_lenlist():
	a = AD(lambda x,y: 3*x**2 + 2*y**3)
	with pytest.raises(Exception):
        	a.get_der(1, 2, 3)
	with pytest.raises(Exception):
			a.get_der([1, 2, 3], [3, 4, 5], [1, 3, 4])

def test_exception():
	fn = AD(my_fn_2d, ndim=2)
	with pytest.raises(Exception):
		fn.get_der([1,2,3])

def my_fn_cos(x):
	return 5*admath.cos(x)

def my_fn_nested_1(x):
	return 5*x**2 * 2*admath.cos(x)

def test_cos():
	cos_fn = AD(my_fn_cos)
	assert cos_fn.get_der(5) == -5*np.sin(5)

def test_nested_1():
	nested_fn = AD(my_fn_nested_1)
	xs = [-10,2,5,10]
	for x in xs:
		assert nested_fn.get_der(x) == pytest.approx(-10*x*(x*np.sin(x)-2*np.cos(x)))

def my_fn_nested_2(x):
	return 5*admath.log(admath.sin(x))

def test_nested_2():
	nested_fn = AD(my_fn_nested_2)
	xs = [0.4, 0.9, 1.2]
	for x in xs:
		assert nested_fn.get_der(x) == pytest.approx(5/np.tan(x))


from PIL import Image
import numba
import numpy as np

MAX_ITER = 1000
MAX_RADIUS = 2
SIZE_Image = 500

START_POINT = (0, 0)
ZOOM = 1
RANGE = 1 / ZOOM

C = complex(-0.761576,-0.0847596)
# C = complex(-1, 0)
START_X = START_POINT[0] - RANGE
END_X = START_POINT[0] + RANGE
STEP_X = (END_X - START_X) / SIZE_Image

START_Y = START_POINT[1] + RANGE
END_Y = START_POINT[1] - RANGE
STEP_Y = (END_Y - START_Y) / SIZE_Image

BLACK = (0,0,0)
WHITE = (255,255,255)

@numba.jit(nopython=True)
def calc(z, c):
    return z ** 2 + c

@numba.jit(nopython=True)
def explode(z):
    for i in range(MAX_ITER):
        z = calc(z, C)
        if abs(z) > MAX_RADIUS:
            return i
    return i

@numba.jit(nopython=True)
def loop(arr):
    j = START_Y
    for y in range(SIZE_Image):
        i = START_X
        for x in range(SIZE_Image):
            z = complex(i, j)
            e = explode(z)
            if e < MAX_ITER:
                color = round(e*255)/MAX_ITER
                arr[y, x]  = (color, color, color)
            else:
                arr[y, x] = (0, 0, 0)
            i += STEP_X
        j += STEP_Y

def run():
    arr = np.empty([SIZE_Image,SIZE_Image, 3])
    loop(arr)
    img = Image.fromarray(np.uint8(arr))
    img.save("result_julia.jpg", "JPEG")

if __name__ == "__main__":
    run()


#! /usr/bin/env python
# -*- coding: utf-8 -*-
# vim:fenc=utf-8
#
# Copyright © 2019 Jinsong Liu <jinsongliu@utexas.edu>
#
# Distributed under terms of the GNU-License license.

"""

"""
import numpy as np
from . import spectrums
import inspect

class PowerSpectrum(object):
    """
    Reference: https://www.imft.fr/IMG/pdf/psdtheory.pdf  "The Power Spectral Density and the Autocorrelation"
    Definitions:
    - ACF: for a real, stationary signal x(t), its ACF R is defined as: R(tau) = E[x(t)x(t+tau)]
    - PSD: Fourier transform of R(tau) is called the Power spectral denstity (PSD), Sx/pxx
    => Sx(w_rad) = \int R(tau) exp(-2*pi*j*w_rad*tau) d tau

    Properties:
    1. since Sx is an average of the magnitude squared of the Fourier transform
        Sx(w_rad) = lim T->inf 1/T E[|X_T(w_rad)|^2],
        where X_T(w_rad) is the Fourier transform of x(t), X_T(w_rad) = int x(t) exp(-2*pi*j*w_rad*t) dt

    2. Sx(-w_rad) = Sx(w_rad)
    3. Dual relationship: R(tau) = int Sx(w_rad) exp(2*pi*j*w_rad*tau) d tau
    4. At tau=0, R(0) = E[x(t)^2] = int Sx(w_rad) dw, "variance" = Area under curve
    5. Parseval's Identity:
        Assume x(t) ergodic in the autocorrelation, i.e. R(tau) = E[x(t) x(t+tau)] = \lim_{T->inf} 1/T \int_{-T/2} ^{T/2} x(t) x(t+tau) dt
        for any signal x(t):
        lim_{T->inf} 1/T \int _{-T/2} ^{T/2} x(t)^2 dt = \int_{-inf} ^{inf} Sx(w_rad) dw

    """

    def __init__(self, name=None, *args):
        self.name   = name
        self.sides  = 'single'
        self.args   = args
        if self.name is None:
            self.ndim = None
        elif isinstance(self.name, str):
            self.name = self.name.lower()
            try:
                self.density_func = getattr(spectrums, self.name.lower())
                sig = inspect.signature(self.density_func)
                self.ndim = len(sig.parameters) - 1
            except AttributeError as e:
                self.ndim = None
                raise ValueError(e)
        else:
            raise ValueError("'module 'uqra.solver.spectrums' has no attribute '{}'".format(self.name))

    def set_density(self, w_rad, pxx, sides='single'):
        assert w_rad.shape == pxx.shape, 'w_rad and pxx should have same shape. w_rad.shape={}, pxx.shape={}'.format(w_rad.shape, pxx.shape)
        self.w_rad  = w_rad
        self.pxx    = pxx
        self.sides  = sides
        self.dw     = w_rad[1] -w_rad[0]

    def cal_density(self, w_rad):
        w_rad, pxx = self.density_func(w_rad, *self.args)
        assert w_rad.shape == pxx.shape, 'w_rad and pxx should have same shape. w_rad.shape={}, pxx.shape={}'.format(w_rad.shape, pxx.shape)
        self.w_rad= w_rad
        self.pxx  = pxx
        self.dw   = w_rad[1] - w_rad[0]
        return pxx

    def get_acf(self):
        """
        Return Autocorrelation function corresponding to the specified power spectrum assuming stationary process by Inverse Fourier Transform (R=IFFT(PSD))
        PowerSpectrum.sides = 'double'
        """
        # ---------------------------------------------------------
        #                   |   Range       |   delta step
        # Time domain       | [-tmax, tmax] | dt = given
        # Frequency domain  | [-fmax, fmax] | dw = 1/(2(tmax))
        #                   | fmax = 1/(2*dt)
        # ---------------------------------------------------------
        # for single side psd, transform to double side and return corresponding w_rad, pxx
        # Transformation shouldn't change obj.w_rad, obj.pxx
        if not self._is_symmetric(self.w_rad, self.pxx):
            psd_w, psd_pxx = self.psd_single2double()
        else:
            psd_w   = self.w_rad
            psd_pxx = self.pxx

        nfrequencies    = psd_w.size
        w_min, w_max, dw= self.w_rad[0], self.w_rad[-1], self.w_rad[1]-self.w_rad[0]
        dt              = 1.0*2*np.pi/(2*w_max)
        acf_ifft        = np.fft.ifft(psd_pxx) / dt
        acf             = np.sqrt(acf_ifft.real**2 + acf_ifft.imag**2)
        t               = np.arange(-nfrequencies//2, nfrequencies//2) * dt
        acf             = np.roll(acf,nfrequencies//2)
        assert t.size == acf.size
        return t, acf

    def from_acf(self, t, acf_t):
        """
        Given auto correlation function acf_tau in [0,t] with dtau, return corresponding power spectral density function
        Process is assumed to be stationary such that acf is just a function of tau and acf is symmetric. e.g. acf(-tau) = acf(tau)
        Arguments:
            tau: time interval, if only [0,tmax] is specified, [-tmax,0) will be pre-appended automatically
                Values of acf at both positive and negative lags (tau) is necessary. When applying fft(data), algorithm assumes data repeat after time interval. If only positive part provided, symmetric information of acf will not be passed ([-tmax,0] will be exactly same as [0, tmax] instead of symmetric acf(tau) = acf(-tau))
            acf: autocorrelation function or values at specified tau
        Returns:
            Power spectral density function
            psd_w, psd_pxx
        """

        t, acf_t= self._correct_acf_format(t, acf_t)
        dt      = t[1]-t[0]
        psd_pxx = np.fft.fft(acf_t).real * dt
        psd_w   = 2*np.pi*np.fft.fftfreq(t.size,d=dt)
        # Since we know acf function is even, fft of acf_tau should only contain real parts
        # psd_pxx = np.sqrt(acf_fft.real**2 + acf_fft.imag**2) * dtau

        # reorder frequency from negative to positive ascending order
        psd_pxx = np.array([x for _,x in sorted(zip(psd_w,psd_pxx))])
        psd_w   = np.array([x for _,x in sorted(zip(psd_w,psd_w))])
        self.w_rad  = psd_w
        self.pxx= psd_pxx
        self.sides='double'
        return psd_w, psd_pxx

    def gen_process(self,t=None, phase=None, random_seed=None):
        """
        Generate Gaussian time series for given spectrum with IFFT method
        Note: For one side psd, one need to create IFFT coefficients for negative frequencies to use IFFT method.
            Single side psd need to be divide by 2 to create double side psd, S1(self.w_rad) = S1(-self.w_rad) = S2(self.w_rad)/2
            Phase: theta(self.w_rad) = -theta(-self.w_rad)

        Arguments: optional
            t: time index, start 0 to tmax
            phase: phase uniformly between[-pi, pi]
            random_seed: seed to generate phase if phase is not given
        Return:
            psd_w: frequencies of spectral density
            eta_fft_coeffs: surface wave power spectral denstiy

        """
        # ---------------------------------------------------------
        #                   |   Range       |   delta step
        # Time domain       | [0, tmax]     | dt = given
        # Frequency domain  | [-fmax, fmax] | dw = 1/tmax
        #                   | fmax = 1/(2*dt)
        # ---------------------------------------------------------
        if self.sides.lower() == 'single':
            psd_w, pxx = self.w_rad , self.pxx
            # psd_w, pxx= self.psd_single2double()
        else:
            raise NotImplementedError
            assert self._is_symmetric(self.w_rad, self.pxx)
            psd_w, pxx = self.w_rad, self.pxx

        psd_w_min, psd_w_max, psd_dw = np.amin(abs(psd_w)), np.amax(abs(psd_w)) , psd_w[1]-psd_w[0]
        if t is None:
            ### if t is not given, returned time series will be generated based on specified frequency values in psd_w
            tmin, tmax, dt = 0, 2*np.pi/psd_dw, np.pi/psd_w_max
            fft_freq_min, fft_freq_max, fft_freq_dw = 0, psd_w_max, psd_dw
            fft_freq_pos = np.arange(int(round(fft_freq_max/fft_freq_dw) +1)) * fft_freq_dw
            time = np.arange(int(round(tmax/dt))+1) *dt
        else:
            ### when a time index is given, sampling frequency need to be small enough to cover the period (tmax)
            ### and frequency window need to be large enough to have time resolution dt
            tmax, tmin, dt = t[-1], t[0], t[1] - t[0]
            fft_freq_min, fft_freq_max, fft_freq_dw = 0, max(np.pi/dt, psd_w_max), min(psd_dw, 2*np.pi/tmax)
            fft_freq_pos = np.arange(int(round(fft_freq_max/fft_freq_dw) +1)) * fft_freq_dw
            tmin, tmax, dt = 0, 2*np.pi/fft_freq_dw, np.pi/fft_freq_max
            time = np.arange(int(round(tmax/dt))+1) *dt

        psd_w_idx = [int(round(psd_w_min/fft_freq_dw)),int(round(psd_w_max/fft_freq_dw))]
        if phase is None:
            np.random.seed(random_seed)
            theta = np.random.uniform(-np.pi, np.pi, psd_w.size)
        else:
            theta = phase[:psd_w.size]

        print('time:', time.shape)
        print('theta:', theta.shape)
        psd_A = np.sqrt(2.0*pxx*fft_freq_dw)/2.0 * np.exp(-1j*theta) *  (pxx.size*2-1) #(fft_freq_pos*2-1) # amplitude
        # fft_A = np.zeros(fft_freq_pos.size, dtype=complex)
        # fft_A = np.zeros(pxx.size, dtype=complex)
        # fft_A[psd_w_idx[0]:psd_w_idx[1]] = psd_A
        fft_A = psd_A
        fft_A = np.append(fft_A, np.flip(np.conj(fft_A[1:])))
        # eta = np.roll(eta,ntime_steps).real # roll back to [-T, T], IFFT result should be real, imaginary part is very small ~10^-16
        eta = np.fft.ifft(fft_A).real
        if eta.size != time.size:
            raise ValueError(' len(eta)= {:d}, but len(time) = {:d}'.format(eta.size, time.size))

        if t is not None:
            eta = np.interp(t, time, eta)
            time = t
        return time, eta , psd_w, theta

    def _is_symmetric(self, x, y):
        """
        Check if the following two symmetric properties are met:
        1. x[i] = -x[i]
        2. y[x] = -y[x]
        """
        x = np.array(x)
        y = np.array(y)
        x = x[x.argsort()]
        y = y[x.argsort()]
        assert x.size == y.size

        if x[0] * x[-1] >= 0: # return false if xmin, xmax same sign
            return False
        n     = x.size+1 if (x.size) %2 else x.size
        bool1 = np.array_equal(x[1:n/2], -np.flip(x[n/2:-1]))
        bool2 = np.array_equal(y[1:n/2], -np.flip(y[n/2:-1]))
        return bool1 and bool2

    def _correct_acf_format(self, t, acf_t):
        """
        Modify (t, acf_t) to standard format corresponding to frequenceis
        t = [0,1,...,n, -n,...,-1] * dt
        2n+1 time steps
        """
        t     = np.array(t)
        t     = t[t.argsort()]
        acf_t = acf_t[t.argsort()]

        ntimesteps = t.size
        ## if not symmetric, following steps are taken:
        # 1. time step dt is taken as the mean value of all time steps
        # 2. corresponding acf values are interpolated
        if not self._is_symmetric(t, acf_t):
            dt = np.mean(t[1:-1] - t[:-2], dtype=np.float64)
            ntimesteps = np.ceil(max(abs(t))/dt)
            t1 = np.arange(-ntimesteps, ntimesteps) * dt
            acf_t_interp = np.interp(t1, t, acf_t)
            return np.roll(t1, ntimesteps+1), np.roll(acf_t_interp, ntimesteps+1)
        else:
            return t, acf_t

    def psd_single2double(self):
        """
        Convert single side psd specified by (w_rad, pxx) to double side
        Arguments:
            w_rad   : single side frequency vector, could start from arbitrary value
            pxx : single side power spectral density (PSD) estimate, pxx,
        Returns:
            ww_rad  : double side frequency vector
            pxx2: double side power spectral density (PSD) estimate, pxx2
        """
        assert self.w_rad is not None and self.pxx is not None
        w_rad, pxx = self.w_rad, self.pxx
        ## sorting w_rad in ascending order
        w_rad= w_rad[w_rad.argsort()]
        pxx = pxx [w_rad.argsort()]
        assert w_rad[0] >= 0 and w_rad[-1] >0 # make sure frequency vector in positive range
        dw      = np.mean(w_rad[1:]-w_rad[:-1], dtype=np.float64) # dw is the average frequency difference
        N       = len(np.arange(w_rad[-1], 0, -dw)) # does not include 0
        pxx2    = np.zeros(2*N+1)
        ww_rad  = np.zeros(2*N+1)
        # print(ww_rad.shape, pxx2.shape)
        #
        # pxx2: [0,|1,2,...,N | N+1,...,2N+1]
        #       [0,| positive |   negative  ]

        ## padding psd from 0 to w_rad[0] with 0
        # first element of pxx2[0] is power at frequency 0. If pxx(0) is not given, 0 is padded
        pxx2[0] = pxx[0] if w_rad[0]==0 else 0
        # Positive frequencies part
        m = pxx.size
        pxx2[N+1-m:N+1] = pxx/2
        # Negative frequencies part
        pxx2[N+1:]  = np.flip(pxx2[1:N+1])
        ww_rad[1:N+1]   = np.flip(np.arange(w_rad[-1], 0, -dw))
        ww_rad[N+1:]    = -np.arange(w_rad[-1], 0, -dw)

        ## Reorder psd to [-inf, negative, 0, positive, +inf]
        pxx2= np.roll(pxx2, N)
        ww_rad  = np.roll(ww_rad, N)

        return ww_rad, pxx2

    def _gen_process_sum(self):
        if self.sides.lower() == 'double':
            raise NotImplementedError('Stay tuned')
        else:
            psd_w, psd_pxx = self.w_rad, self.pxx
            w_max, dw = psd_w[-1]  , psd_w[1]-psd_w[0]
            tmax, dt = 0.5*2*np.pi/dw , 0.5/w_max
            N = int(tmax/dt)
            t = np.arange(-N,N+1) * dt
            # tmax = t[-1]
            theta = np.random.uniform(-np.pi, np.pi, len(psd_w))
            # Direct sum with single side psd
            ampf = np.sqrt(2*psd_pxx*(dw)) # amplitude

            # Reshape to matrix operation format
            ampf  = np.reshape(ampf,  (N+1,1))
            psd_w = np.reshape(psd_w, (N+1,1))
            theta = np.reshape(theta, (N+1,1))
            t     = np.reshape(t,     (1, 2*N+1))
            eta = np.sum(ampf * np.cos(2*np.pi*psd_w*t + theta),axis=0)

        return t, eta


from __future__ import unicode_literals
from math import sqrt
import random
from random import randint as rand
from random import getrandbits
import sympy
import time
import binascii

def gcd(a, b):
    if b == 0:
        return a
    else:
        return gcd(b, a % b)

def egcd(a, b):
    x,y, u,v = 0,1, 1,0
    while a != 0:
        q, r = b//a, b%a
        m, n = x-u*q, y-v*q
        b,a, x,y, u,v = a,r, u,v, m,n
    return b, x, y

def mod_inverse(a, m):
    g, x, y = egcd(a, m)
    if g != 1:
        return None
    else:
        return x % m

def isprime(n):
    if n < 2:
        return False
    elif n == 2:
        return True
    else:
        for i in range(1, int(sqrt(n)) + 1):
            if n % i == 0:
                return False
    return True

def generate_prime(bitlength):
    a = '1'+'0'*(bitlength-1)
    b = '1'*bitlength

    p = sympy.randprime(int(a, 2), int(b, 2))
    return p

def generate_keypair(keysize):
    p = generate_prime(keysize)
    q = generate_prime(keysize)
    print(p, q)
    n = p * q
    phi = (p-1)*(q-1)//gcd(p-1, q-1)
    e = sympy.randprime(1,phi)
    d = mod_inverse(e,phi)
    if e != d:
        return ((e, n), (d, n))

def encrypt(plain_text, package):
    e, n = package
    if plain_text > n:
        print('Message is too large for key to handle')
    msg_ciphertext = pow(plain_text, e, n)
    return msg_ciphertext

def decrypt(msg_ciphertext, package):
    d, n = package
    msg_plaintext = pow(msg_ciphertext, d, n)
    return binascii.unhexlify(hex(msg_plaintext)[2:]).decode()

public, private = generate_keypair(1024)
print('Public Key : ',public)
print('Private Key : ',private)

msg = input("Write msg: ")

hex_data   = binascii.hexlify(msg.encode())
plain_text = int(hex_data, 16)

t1 = time.time()
encrypted_msg = encrypt(plain_text, public)
print("Encrypted msg: " + str(encrypted_msg))

decrypted_msg = decrypt(encrypted_msg, private)
print("Decrypted msg: " + str(decrypted_msg))
print('Runtime : ' + str(time.time()-t1) + ' seconds')


 import numpy as np
from sklearn import preprocessing

data = np.array([[ 3, -1.5,  2, -5.4],
                 [ 0,  4,  -0.3, 2.1],
                 [ 1,  3.3, -1.9, -4.3]])

# mean removal
data_standardized = preprocessing.scale(data)
print('\n Mean =',data_standardized.mean(axis=0))
print('Std deviation =', data_standardized.std(axis=0))

# min max scaling
data_scaler = preprocessing.MinMaxScaler(feature_range=(0, 1))
data_scaled = data_scaler.fit_transform(data)
print('\nMin max scaled data:\n', data_scaled)

# normalization
data_normalized = preprocessing.normalize(data, norm='l1')
print('\nL1 normalized data:\n', data_normalized)

# binarization
data_binarized = preprocessing.Binarizer(threshold=1.4).transform(data)
print('\nBinarized data:\n', data_binarized)

# one hot encoding
encoder = preprocessing.OneHotEncoder()
encoder.fit([[0, 2, 1, 12], [1, 3, 5, 3], [2, 3, 2, 12], [1, 2, 4, 3]])
encoded_vector = encoder.transform([[2, 3, 5, 3]]).toarray()
print('\nEncoded vector:\n', encoded_vector)


import numpy as np

def diffdrive(x, y, theta, v_l, v_r, t, l):
    # straight line
    if (v_l == v_r):
        theta_n = theta
        x_n = x + v_l * t * np.cos(theta)
        y_n = y + v_l * t * np.sin(theta)
    # circular motion
    else:
        # Calculate the radius
        R = l / 2.0 * ((v_l + v_r) / (v_r - v_l))
        # computing center of curvature
        ICC_x = x - R * np.sin(theta)
        ICC_y = y + R * np.cos(theta)
        # compute the angular velocity
        omega = (v_r - v_l) / l
        # computing angle change
        dtheta = omega * t
        # forward kinematics for differential drive
        x_n = np.cos(dtheta) * (x - ICC_x) - np.sin(dtheta) * (y - ICC_y) + ICC_x
        y_n = np.sin(dtheta) * (x - ICC_x) + np.cos(dtheta) * (y - ICC_y) + ICC_y
        theta_n = theta + dtheta

    return x_n, y_n, theta_n


from song_data import songs
import numpy as np

#Create the variables songs_q1, songs_q2, and songs_q3 here:
songs_q1 = np.quantile(songs, 0.25)
songs_q2 = np.quantile(songs, 0.5)
songs_q3 = np.quantile(songs, 0.75)

favorite_song = 100
quarter = 1

#Ignore the code below here:
try:
  print("The first quartile of dataset one is " + str(songs_q1) + " seconds")
except NameError:
  print("You haven't defined songs_q1")
try:
  print("The second quartile of dataset one is " + str(songs_q2)+ " seconds")
except NameError:
  print("You haven't defined songs_q2")
try:
  print("The third quartile of dataset one is " + str(songs_q3)+ " seconds")
except NameError:
  print("You haven't defined songs_q3\n")

Data Scientist Career Path/7. Summary Statistics/5. Quartiles, Quantiles, Interquartile Range/1. Quartiles/5. numpy.py


from __future__ import division
from __future__ import absolute_import
import numpy as np
import pandas as pd
import scipy as sp
from rankit.Table import Table
from scipy.sparse import coo_matrix
from scipy.sparse.linalg import lsqr
from .matrix_build import fast_colley_build
from numpy.linalg import norm

class UnsupervisedRanker(object):
    """Base class for all unsupervised ranking algorithms."""
    def rank(self, table, **kargs):
        raise NotImplementedError("UnsupervisedRanker is a abstract class.")

    def _showcase(self, table, ascending=False):
        # one need to translate item index to item name.
        indexlut = table.indexlut
        rating = self.rating # iitm, rating
        itemname = []
        for row in rating.itertuples(index=False, name=None):
            itemname.append(indexlut[row[0]])
        rst = pd.DataFrame({
            "name": itemname,
            "rating": rating["rating"]})
        rst['rank'] = rst.rating.rank(method='min', ascending=ascending).astype(np.int32)
        return rst.sort_values(by=['rating', 'name'], ascending=ascending).reset_index(drop=True)

class MasseyRanker(UnsupervisedRanker):
    """Massey ranking system proposed by Kenneth Massey: Statistical models applied to the rating of sports teams.
    Bachelor's thesis, Bluefield College, 1997.
    Core idea: The competition score difference is the rating difference, so one can solve a linear equation by minimize least square error.

    Parameters
    ----------
    drawMargin: [0, +Inf), default 0.
        When absolute difference between two teams are smaller than drawMargin, this competition is considered as a tie.
    """
    def __init__(self, drawMargin = 0.0):
        self.drawMargin = drawMargin

    def rank(self, table):
        """Calculate the rank and rating with specified parameters.

        Parameters
        ----------
        table: Table
            The record table to be ranked, should be a Table object.

        Returns
        -------
        pandas.DataFrame, with column ['name', 'rating', 'rank']
        """
        drawMargin = self.drawMargin
        data = table.table[['hidx', 'vidx', 'hscore', 'vscore', 'weight']]

        m = data.shape[0]
        n = table.itemnum
        y = np.zeros(m)
        dat = np.zeros(m*2, dtype=np.float)
        col = np.zeros(m*2, dtype=np.int)
        row = np.zeros(m*2, dtype=np.int)
        for i, itm in enumerate(data.itertuples(index=False, name=None)):
            row[i*2]=i; col[i*2]=itm[0]; dat[i*2]=itm[4];
            row[i*2+1]=i; col[i*2+1]=itm[1]; dat[i*2+1]=-itm[4];
            if np.abs(itm[2]-itm[3])<=drawMargin:
                y[i]=0.0
            else:
                y[i] = itm[4]*(itm[2]-itm[3])

        X = coo_matrix((dat, (row, col)), shape=(m, n))
        X = X.tocsr()

        rst = lsqr(X, y)
        rating = rst[0]
        if hasattr(self, "rating"):
            self.rating["rating"] = rating
        else:
            self.rating = pd.DataFrame({
                "iidx": np.arange(n, dtype=np.int),
                "rating": rating})

        return self._showcase(table, False)

class ColleyRanker(UnsupervisedRanker):
    """Colley ranking system proposed by Wesley Colley:
    Colley's bias free college football ranking method: The colley matrix explained, 2002.
    http://www.colleyrankings.com
    Core idea: All team's rating starts from 0.5, and with evolvement of games, the rating of each player deviates from 0.5
    according to probability of win. However, the average rating of all teams remains 0.5.

    Parameters
    ----------
    drawMargin: [0, +Inf), default 0.
        When absolute difference between two teams are smaller than drawMargin, this competition is considered as a tie.
    """
    def __init__(self, drawMargin = 0.0):
        self.drawMargin = drawMargin

    def rank(self, table):
        """Calculate the rank and rating with specified parameters.

        Parameters
        ----------
        table: Table
            The record table to be ranked, should be a Table object.

        Returns
        -------
        pandas.DataFrame, with column ['name', 'rating', 'rank']
        """
        drawMargin = self.drawMargin
        data = table.table[['hidx', 'vidx', 'hscore', 'vscore', 'weight']]

        idx = data.iloc[:, :2]
        score = data.iloc[:, 2:]
        C, b = fast_colley_build(np.require(idx, dtype=np.int32), np.require(score, dtype=np.float64),
                                 table.itemnum, drawMargin)

        rating = sp.linalg.solve(C, b)
        if hasattr(self, "rating"):
            self.rating["rating"] = rating
        else:
            self.rating = pd.DataFrame({
                "iidx": np.arange(table.itemnum, dtype=np.int),
                "rating": rating})

        return self._showcase(table, False)

class KeenerRanker(UnsupervisedRanker):
    """Keener ranking system proposed by James Keener:
    The Perron-Frobenius theorem and the ranking of football teams, SIAM Review, 35(1):80-93, 1993
    The core idea are: 1. rating is proportional to real strength; 2. real strength is measured relatively by competitors' strength.

    Parameters
    ----------
    func: default None.
        If set, the score difference should be transformed by the function first then used for rating calculation.
    epsilon: [0, +Inf) default 1e-4
        The small value that applies an interference to game result that force each team had at least one game with each other.
    threshold: (0, +Inf), default 1e-4
        The threshold that controls when the algorithm will converge.
    """
    def __init__(self, func=None, epsilon=1e-4, threshold=1e-4):
        self.func = func
        self.epsilon = epsilon
        self.threshold = threshold

    def rank(self, table):
        """Calculate the rank and rating with specified parameters.

        Parameters
        ----------
        table: Table
            The record table to be ranked, should be a Table object.

        Returns
        -------
        pandas.DataFrame, with column ['name', 'rating', 'rank']
        """
        func, epsilon, threshold = self.func, self.epsilon, self.threshold
        mtx = pd.DataFrame(data={
            'hidx': pd.concat([table.table.hidx, table.table.vidx]),
            'vidx': pd.concat([table.table.vidx, table.table.hidx]),
            'hscore': pd.concat([table.table.hscore, table.table.vscore]),
            'vscore': pd.concat([table.table.vscore, table.table.hscore]),
            'weight': pd.concat([table.table.weight, table.table.weight])
        }, columns = ['hidx', 'vidx', 'hscore', 'vscore', 'weight']).reset_index(drop=True)
        mtx['score'] = mtx.hscore+mtx.vscore
        mtx['hscore'] = (mtx['hscore']+1)/(mtx['score']+2)
        mtx['vscore'] = (mtx['vscore']+1)/(mtx['score']+2)
        if func is not None:
            mtx['hscore'] = mtx.hscore.apply(func)
            mtx['vscore'] = mtx.vscore.apply(func)
        mtx['hscore'] = mtx['hscore']*mtx['weight']
        mtx['vscore'] = mtx['vscore']*mtx['weight']
        mtx = mtx.groupby(['hidx', 'vidx'])[['hscore', 'vscore']].mean()
        mtx.reset_index(inplace=True)

        D = coo_matrix((mtx.hscore.values, (mtx.hidx.values, mtx.vidx.values)), shape=(table.itemnum, table.itemnum)).tocsr()

        r = np.ones(table.itemnum)/table.itemnum
        pr = np.ones(table.itemnum)
        while norm(pr-r)>threshold:
            pr = r
            rho = np.sum(r)*epsilon
            r = D.dot(r)+rho*np.ones(table.itemnum)
            r /= np.sum(r)

        if hasattr(self, "rating"):
            self.rating["rating"] = r
        else:
            self.rating = pd.DataFrame({
                "iidx": np.arange(table.itemnum, dtype=np.int),
                "rating": r})
        return self._showcase(table, False)

class MarkovRanker(UnsupervisedRanker):
    """Markov ranking is actually PageRank.
    The core idea is voting: in each game, each team will vote to each other by the number of scores they lost.
    If there are multiple games for a certain pair of player, their scores will be grouped and averaged.

    Parameters
    ----------
    restart: [0, 1], default 0.3.
        Random walk with restart: in order to avoid black hole in random walk graph.
    threshold: (0, +Inf), default 1e-4
        The threshold that controls when the algorithm will converge.
    """
    def __init__(self, restart=0.3, threshold=1e-4):
        self.restart = restart
        self.threshold = threshold

    def rank(self, table):
        """Calculate the rank and rating with specified parameters.

        Parameters
        ----------
        table: Table
            The record table to be ranked, should be a Table object.

        Returns
        -------
        pandas.DataFrame, with column ['name', 'rating', 'rank']
        """
        restart, threshold = self.restart, self.threshold
        if restart>1 or restart<0:
            raise ValueError("restart rate should be between 0 and 1.")
        mtx = pd.DataFrame(data={
            'hidx': pd.concat([table.table.hidx, table.table.vidx]),
            'vidx': pd.concat([table.table.vidx, table.table.hidx]),
            'hscore': pd.concat([table.table.hscore, table.table.vscore]),
            'vscore': pd.concat([table.table.vscore, table.table.hscore]),
            'weight': pd.concat([table.table.weight, table.table.weight])
        }, columns = ['hidx', 'vidx', 'hscore', 'vscore', 'weight']).reset_index(drop=True)
        mtx['hscore'] = mtx['hscore']*mtx['weight']
        mtx['vscore'] = mtx['vscore']*mtx['weight']

        mtx_ = mtx.groupby('hidx').vscore.sum().rename('htotalvote')

        mtx = mtx.groupby(['hidx', 'vidx'])[['hscore', 'vscore']].mean()
        mtx = pd.concat([mtx.reset_index().set_index('hidx'), mtx_], axis=1).reset_index()
        mtx['prob'] = mtx['vscore']/mtx['htotalvote']

        D = coo_matrix((mtx.prob.values, (mtx.hidx.values, mtx.vidx.values)), shape=(table.itemnum, table.itemnum)).transpose().tocsr()
        r = np.ones(table.itemnum)/table.itemnum
        pr = np.ones(table.itemnum)
        while norm(pr-r)>threshold:
            pr = r
            vrestart = restart*np.ones(table.itemnum)/table.itemnum
            r = (1-restart)*D.dot(r)+vrestart
            r /= np.sum(r)

        if hasattr(self, "rating"):
            self.rating["rating"] = r
        else:
            self.rating = pd.DataFrame({
                "iidx": np.arange(table.itemnum, dtype=np.int),
                "rating": r})
        return self._showcase(table, False)

class ODRanker(UnsupervisedRanker):
    """The Offence-defence rank tries to assign an offence rating and a defence rating to each team.
    By saying "offence rating", we assume that a team has a high offence rating when it gained a lot of points
    from a team good in defence. Vise versa. The offence rating of a team is associated with defence rating of each
    competitor in a non-linear way. The defence rating of a team is also non-linearly related to each competitors'
    offence rating.

    Parameters
    ----------
    method: {'summary', 'offence', 'defence'}, default 'summary'.
        The rating to be returned. 'summary' is offence/defence.
    epsilon: [0, +Inf) default 1e-4
        The small value that forces a convergence.
    threshold: (0, +Inf), default 1e-4
        The threshold that controls when the algorithm will converge.
    """
    def __init__(self, method='summary', epsilon=1e-4, threshold=1e-4):
        self.method = method
        self.epsilon = epsilon
        self.threshold = threshold

    def rank(self, table):
        """Calculate the rank and rating with specified parameters.

        Parameters
        ----------
        table: Table
            The record table to be ranked, should be a Table object.

        Returns
        -------
        pandas.DataFrame, with column ['name', 'rating', 'rank']
        """
        method, epsilon, threshold = self.method, self.epsilon, self.threshold
        mtx = pd.DataFrame(data={
            'hidx': pd.concat([table.table.hidx, table.table.vidx]),
            'vidx': pd.concat([table.table.vidx, table.table.hidx]),
            'hscore': pd.concat([table.table.hscore, table.table.vscore]),
            'vscore': pd.concat([table.table.vscore, table.table.hscore]),
            'weight': pd.concat([table.table.weight, table.table.weight])
        }, columns = ['hidx', 'vidx', 'hscore', 'vscore', 'weight']).reset_index(drop=True)
        mtx['hscore'] = mtx['hscore']*mtx['weight']
        mtx['vscore'] = mtx['vscore']*mtx['weight']
        mtx = mtx.groupby(['hidx', 'vidx'])[['hscore', 'vscore']].mean()
        mtx.reset_index(inplace=True)

        D = coo_matrix((mtx.vscore.values, (mtx.hidx.values, mtx.vidx.values)), shape=(table.itemnum, table.itemnum)).tocsr()
        Dt = D.transpose()

        prevd = np.ones(table.itemnum)/table.itemnum
        d = np.ones(table.itemnum)
        while norm(prevd-d)>threshold:
            prevd = d
            o = Dt.dot(1/d)+np.ones(d.shape[0])*epsilon*(np.sum(1/d))
            d = D.dot(1/o)+np.ones(o.shape[0])*epsilon*(np.sum(1/o))
        o = Dt.dot(1/d)

        if method=='summary':
            r = o/d
        elif method=='offence':
            r = o
        elif method=='defence':
            r = d
        else:
            raise ValueError('output should be one of summary, offence or defence.')
        if hasattr(self, "rating"):
            self.rating["rating"] = r
        else:
            self.rating = pd.DataFrame({
                "iidx": np.arange(table.itemnum, dtype=np.int),
                "rating": r})
        return self._showcase(table, True if method=='defence' else False)

class DifferenceRanker(UnsupervisedRanker):
    """This ranker targets at predicting score difference of games directly.
    The difference of ratings are proportional to the difference of score.
    """
    def rank(self, table):
        """Calculate the rank and rating with specified parameters.

        Parameters
        ----------
        table: Table
            The record table to be ranked, should be a Table object.

        Returns
        -------
        pandas.DataFrame, with column ['name', 'rating', 'rank']
        """
        mtx = pd.DataFrame(data={
            'hidx': pd.concat([table.table.hidx, table.table.vidx]),
            'vidx': pd.concat([table.table.vidx, table.table.hidx]),
            'hscore': pd.concat([table.table.hscore, table.table.vscore]),
            'vscore': pd.concat([table.table.vscore, table.table.hscore]),
            'weight': pd.concat([table.table.weight, table.table.weight])
        }, columns = ['hidx', 'vidx', 'hscore', 'vscore', 'weight']).reset_index(drop=True)
        mtx['score'] = mtx['hscore']-mtx['vscore']
        mtx['score'] = mtx['score']*mtx['weight']
        mtx = mtx.groupby(['hidx', 'vidx']).score.mean().reset_index()
        r = mtx.groupby('hidx').score.sum()/table.itemnum
        r = r.sort_index()

        if hasattr(self, "rating"):
            self.rating["rating"] = r.values
        else:
            self.rating = pd.DataFrame({
                "iidx": np.arange(table.itemnum, dtype=np.int),
                "rating": r})
        return self._showcase(table, False)

import numpy,from numpy,import scipy,from scipy


import numpy as np

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

class QDA_model:

    def fit(self, X, y):
        self.pi = np.sum(y==1)/len(y)
        self.mu1 = np.mean(X[y==1], axis=0)
        self.mu2 = np.mean(X[y==0], axis=0)

        sigma1 = np.cov(X[y==1].T)
        sigma2 = np.cov(X[y==0].T)
        self.sigma1_inv = np.linalg.inv(sigma1)
        self.sigma2_inv = np.linalg.inv(sigma2)

        self.a = np.log(self.pi/(1-self.pi)) + (1/2)*(self.mu2.T.dot(self.sigma2_inv).dot(self.mu2) -
                                            self.mu1.T.dot(self.sigma1_inv).dot(self.mu1))
        self.b = self.mu1.T.dot(self.sigma1_inv) - self.mu2.T.dot(self.sigma2_inv)

    def compute_frontier(self):

        def frontier(x1, x2):
            interm = np.concatenate((x1[:, :, np.newaxis], x2[:, :, np.newaxis]), axis=2).reshape(-1, 2)
            return self.predict_proba(interm).reshape(x1.shape)

        return frontier

    def predict_proba(self, X):
        return sigmoid(self.a + self.b.dot(X.T) +
                       (1/2)*np.sum(X.dot(self.sigma2_inv-self.sigma1_inv)*X, axis=1))

    def predict(self, X):
        return self.predict_proba(X) > 0.5

    def compute_misclassif_error(self, X, y):
        return np.sum(self.predict(X) != y)/len(y)


import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
import numpy as np
import matplotlib.pyplot as plt

df_wine = pd.read_csv('wine.data', header=None)
df_wine.columns = ['Class label', 'Alcohol', 'Malic acid', 'Ash',
                   'Alcalinity of ash', 'Magnesium', 'Total phenols',
                   'Flavanoids', 'Nonflavanoid phenols', 'Proanthocyanins',
                   'Color intensity', 'Hue',
                   'OD280/OD315 of diluted wines', 'Proline']

# Splitting the data into 70% training and 30% test subsets.
X, y = df_wine.iloc[:, 1:].values, df_wine.iloc[:, 0].values
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, stratify=y, random_state=0)

# Standardizing the data.
sc = StandardScaler()
X_train_std = sc.fit_transform(X_train)
X_test_std = sc.transform(X_test)

cov_mat = np.cov(X_train_std.T)
eigen_vals, eigen_vecs = np.linalg.eig(cov_mat)

print('\nEigenvalues \n%s' % eigen_vals)

# Total and explained variance
tot = sum(eigen_vals)
var_exp = [(i / tot) for i in sorted(eigen_vals, reverse=True)]
cum_var_exp = np.cumsum(var_exp)

plt.bar(range(1, 14), var_exp, alpha=0.5, align='center',
        label='Individual explained variance')
plt.step(range(1, 14), cum_var_exp, where='mid',
         label='Cumulative explained variance')
plt.ylabel('Explained variance ratio')
plt.xlabel('Principal component index')
plt.legend(loc='best')
plt.tight_layout()
plt.show()


#from:  https://stackoverflow.com/questions/50658884/why-this-numba-code-is-6x-slower-than-numpy-code
#setup: import numpy as np; np.random.seed(0); x1 = np.random.random((1, 512)); x2 = np.random.random((10000, 512))
#run: euclidean_distance_square(x1, x2)
#pythran export euclidean_distance_square(float64[1,:], float64[:,:])
import numpy as np
def euclidean_distance_square(x1, x2):
    return -2*np.dot(x1, x2.T) + np.sum(np.square(x1), axis=1)[:, np.newaxis] + np.sum(np.square(x2), axis=1)


import numpy as np
import numpy.linalg as LA

# calculate ACF from l=0~l
def ACF(x, l):
    acf = np.zeros(l+1)
    for i in range(l+1):
        cov_matrix = np.cov(x[:len(x)-i], x[i:])
        acf[i] = cov_matrix[0, 1] / np.sqrt(cov_matrix[0, 0]*cov_matrix[1, 1])
    return acf

# the sample PACF is computed via the
# Durbin-Levinson recursive algorithm
def PACF(x, l, acf=None):
    if acf == None:
        acf = ACF(x, l)
    pacf = np.zeros([l+1, l+1])
    for k in range(1,l+1):
        pacf[k, k] = (acf[k] - np.dot(pacf[k-1, 1:k], acf[k-1:0:-1])) / \
                     (1 - np.dot(pacf[k-1, 1:k], acf[1:k]))
        for j in range(1,k):
            pacf[k, j] = pacf[k-1, j] - pacf[k, k]*pacf[k-1, k-j]

    return pacf

class AR:
    def __init__(self, p=0):
        self.p = p
        self.sigma_a = 0
        self.phi = None
        self.res = None

    def identifyP(self, x, method="PACF"):
        if method == "PACF":
            self.identifyP_PACF(x, epsilon=0.05)

    def identifyP_PACF(self, x, l=20, epsilon=0.05):
        pacf = PACF(x, l)
        for i in range(1, l+1):
            if np.abs(pacf[i, i]) < epsilon:
                self.p = i-1
                break

    def fit(self, x):
        """
        Just a linear regression using least square.
        """
        if self.p == 0: # if did not explicitly assign p
            self.identifyP(x)
        X = np.zeros([len(x)-self.p, self.p+1])
        Y = np.zeros([len(x)-self.p, 1])
        for i in range(len(x)-self.p):
            Y[i, 0] = x[i+self.p]
            X[i, 0] = 1
            X[i, 1:] = x[i:i+self.p] # Caution! Here the order of the input is not the order in the model
        self.phi = np.matmul(np.matmul(LA.inv(np.matmul(X.T, X)), X.T), Y)
        self.res = Y - np.matmul(X, self.phi)
        self.sigma_a = np.sqrt(np.sum(self.res*self.res)/(len(x)-2*self.p-1))

    def predict(self, x, step=1):
        X = np.zeros([1, self.p+1])
        X[0, 0] = 1
        if step == 1:
            return np.matmul(X, self.phi)
        else:
            pred = []
            for _ in range(step):
                pred.append(float(np.matmul(X, self.phi)))
                X[0, 1:-1] = X[0, 2:]
                X[0, -1] = pred[-1]
            return np.array(pred)

if __name__ == '__main__':
    data = np.genfromtxt(r"..\..\data\dgnp82.dat")

    ar3 = AR(3)
    ar3.fit(data)
    print(ar3.phi)
    print(ar3.sigma_a*ar3.sigma_a)
    print(ar3.predict(data, step=8))


from pygeom.geom3d import Vector
from sympy import Symbol, sqrt
from sympy import expand, simplify, trigsimp, expand_trig
from sympy import diff, integrate

class SymbolicVector(Vector):
    x = None
    y = None
    z = None
    def __init__(self, x: Symbol, y: Symbol, z: Symbol):
        super(SymbolicVector, self).__init__(x, y, z)
    def return_magnitude(self):
        return sqrt(self.x**2+self.y**2+self.z**2)
    def simplify(self):
        return SymbolicVector(simplify(self.x),
                              simplify(self.y),
                              simplify(self.z))
    def trigsimp(self):
        return SymbolicVector(trigsimp(self.x),
                              trigsimp(self.y),
                              trigsimp(self.z))
    def expand(self):
        return SymbolicVector(expand(self.x),
                              expand(self.y),
                              expand(self.z))
    def expand_trig(self):
        return SymbolicVector(expand_trig(self.x),
                              expand_trig(self.y),
                              expand_trig(self.z))
    def integrate(self, terms):
        return SymbolicVector(integrate(self.x, terms),
                              integrate(self.y, terms),
                              integrate(self.z, terms))
    def diff(self, sym: Symbol):
        return SymbolicVector(diff(self.x, sym),
                              diff(self.y, sym),
                              diff(self.z, sym))
    def subs(self, *args):
        return SymbolicVector(self.x.subs(*args),
                              self.y.subs(*args),
                              self.z.subs(*args))
    def to_unit(self):
        mag = self.return_magnitude()
        return SymbolicVector(self.x/mag, self.y/mag, self.z/mag)
    def __mul__(self, obj):
        if isinstance(obj, SymbolicVector):
            return self.x*obj.x+self.y*obj.y+self.z*obj.z
        else:
            x = obj*self.x
            y = obj*self.y
            z = obj*self.z
            return SymbolicVector(x, y, z)
    def __rmul__(self, obj):
        return self.__mul__(obj)
    def __truediv__(self, obj):
        x = self.x/obj
        y = self.y/obj
        z = self.z/obj
        return SymbolicVector(x, y, z)
    def __pow__(self, obj):
        if isinstance(obj, SymbolicVector):
            x = self.y*obj.z-self.z*obj.y
            y = self.z*obj.x-self.x*obj.z
            z = self.x*obj.y-self.y*obj.x
            return SymbolicVector(x, y, z)
    def __add__(self, obj):
        if isinstance(obj, SymbolicVector):
            x = self.x+obj.x
            y = self.y+obj.y
            z = self.z+obj.z
            return SymbolicVector(x, y, z)
    def __radd__(self, obj):
        if obj == 0 or obj is None:
            return self
        else:
            return self.__add__(obj)
    def __sub__(self, obj):
        if isinstance(obj, SymbolicVector):
            x = self.x-obj.x
            y = self.y-obj.y
            z = self.z-obj.z
            return SymbolicVector(x, y, z)
    def __pos__(self):
        return SymbolicVector(self.x, self.y, self.z)
    def __neg__(self):
        return SymbolicVector(-self.x, -self.y, -self.z)

def symple_vector(label, **kwargs):
    x = Symbol(f'{label:s}.x', **kwargs)
    y = Symbol(f'{label:s}.y', **kwargs)
    z = Symbol(f'{label:s}.z', **kwargs)
    return SymbolicVector(x, y, z)

ihat = SymbolicVector(1, 0, 0)
jhat = SymbolicVector(0, 1, 0)
khat = SymbolicVector(0, 0, 1)


# -----------------------------
# Author : Mehdi I.
# -----------------------------

import numpy as np

def get_total_number_of_spanning_trees(matrix,nodes_count):
    # STEP 1: Replace all the diagonal elements with the degree of nodes.
    for i in range(nodes_count):
        sum_of_col =0
        for j in range(nodes_count):
            sum_of_col+=matrix[j][i]
        matrix[i][i]=sum_of_col

    # STEP 2: Replace all non-diagonal 1’s with -1.
    for i in range(nodes_count):
        for j in range(nodes_count):
            if i!=j and matrix[i][j]==1:
                matrix[i][j]=-1

    # STEP 3: final result is co-factor of any element ( like 0,0 )
    matrix=np.delete(matrix, 0, 0)
    matrix=np.delete(matrix, 0, 1)

    return abs(round(np.linalg.det(matrix)))

if __name__ == '__main__':

    adjacency_matrix=[]

    # Specifying adjacency matrix of graph
    nodes_count=int(input("Enter your graph's nodes count : "))
    for i in range(nodes_count):
        row=[]
        print('Enter values for row '+str(i+1)+' of adjacency matrix : ')
        for j in range(nodes_count):
            row.append(int(input()))

        adjacency_matrix.append(row)

    print('\n Your Adjacency Matrix : \n')
    for row in adjacency_matrix:
        print(" ".join(map(str,row)))

    print('\n Total number of spanning trees for given graph is:', get_total_number_of_spanning_trees(adjacency_matrix,nodes_count))


from pydec.testing import *

from scipy.misc import factorial, comb

from pydec.math.combinatorial import combinations, permutations

def test_combinations():
    for N in xrange(6):
        L = range(N)
        for K in xrange(N+1):
            C = list(combinations(L,K))
            S = set([ frozenset(x) for x in C])
            ##Check order
            assert_equal(C, sorted(C))
            ##Check number of elements
            assert_equal(len(C), comb(N,K,exact=True))
            ##Make sure each element is unique
            assert_equal(len(S), comb(N,K,exact=True))

def test_permutations():
    assert_equal(list(permutations([])),[])
    for N in xrange(1,6):
        L = range(N)
        P = list(permutations(L))
        S = set([ frozenset(x) for x in P])
        ##Check number of elements
        assert_equal(len(P), factorial(N,exact=True))
        ##Check that there is only 1 unordered element
        assert_equal(len(S), 1)


# Numerical Dynamics in Three Dimensions

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

# Defining Variables
G = 6.67e-11
M = 6.42e23
R = 3.3895e6
m = 100

# simulation time, timestep and time
t_max = 100
dt = 0.1
t_array = np.arange(0, t_max, dt)

# initialise empty lists to record trajectories
position_list = []
velocity_list = []

#position_matrix = np.zeros(shape=(len(t_array),3))
#velocity_matrix = np.zeros(shape=(len(t_array),3))

# 3-element numpy matrices

position_list.append(np.array([0, 1e7, 0]))
velocity = np.array([np.sqrt((G*M)/np.linalg.norm(position_list[0])), 0, 0])
position = position_list[0] + dt*velocity + 0.5*dt*dt*(-G*M*position_list[0]/math.pow(np.linalg.norm(position_list[0]), 3))

"""

Scenario 1 : vx = 0

Scenario 2 : vx = np.sqrt((G*M)/np.linalg.norm(position_list[0]))

Scenario 3 : vx = 2500

Scenario 4 : vx = np.sqrt((2*G*M)/np.linalg.norm(position_list[0]))

"""

for t in t_array:
    for i in range ( 0, len(t_array) - 1 ) :
        if ( np.linalg.norm(position) >= R ) :

            position_list.append(position)
            velocity_list.append(velocity)

            # To calculate gravitational acceleration:
            acceleration = (-G*M*position/math.pow(np.linalg.norm(position), 3))

            # To do a Verlet update:
            position = 2*position - position_list[-2] + dt*dt*acceleration
            velocity = (0.5/dt) * (position - position_list[-2])

        else:
            break

position_y_final = []
position_x_final = []

for i in position_list :
    position_y_final.append(i[1])
    position_x_final.append(i[0])

# Scenario 1 : Straight Down Descent
# Set graph to altitude (y) against time
# Set vx variable to 0
"""
plt.figure(1)
plt.clf()
plt.xlabel('time (s)')
plt.grid()
plt.plot(t_array, position_y_final, label='altitude (m)')
plt.legend()
plt.show()

"""

# Scenario 2 : Circular Orbit
# Set graph to y-coordinate against x-coordinate
# Set vx variable to np.sqrt((G*M)/np.linalg.norm(position))

# Scenario 3 : Elliptical Orbit
# Set graph to y-coordinate against x-coordinate
# Set vx variable to anywhere in between Scenarios 2 and 4

# Scenario 4 : Hyperbolic Escape
# Set graph to y-coordinate against x-coordinate
# Set vx variable to np.sqrt((2*G*M)/np.linalg.norm(position))

plt.figure(2)
plt.clf()
plt.xlabel('y-coordinate (m)')
plt.grid()
plt.plot(position_y_final, position_x_final, label='x-coordinate (m)')
plt.legend()
plt.show()