import numpy as np

def moment(source, maxn=1):
    """Computes moments from a given source.

    Args:
        source (array-like, distribution or arrival):
            data to compute moments for. Treated as a set of samples
            if an array-like, otherwise is expected to have a `moment(k)`
            method (e.g. distribution or arrival process)
        maxn (int): a number of moments to compute.

    Returns:
        ndarray containing computed moments
    """
    if hasattr(source, 'moment'):
        return np.asarray([source.moment(k) for k in range(1, maxn + 1)])
    else:
        n = len(list(source))
        ret = [1./n * sum([pow(x, k) for x in source])
               for k in range(1, maxn + 1)]
        return np.asarray(ret)

def lag(source, maxn=1):
    """Computes lags from a given source.

    Args:
        source (array-like or arrival):
            data to compute moments for. Treated as a set of samples
            if an array-like, otherwise is expected to have a `lag(k)`
            method (e.g. arrival process)
        maxn (int): a number of lags to compute.

    Returns:
        ndarray containing computed lags
    """
    if hasattr(source, 'lag'):
        return np.asarray([source.lag(k) for k in range(1, maxn + 1)])
    else:
        n = len(list(source))
        maxn = min(maxn, n - 1)  # need at least k + 1 samples for k-th lag
        moments = moment(source, 2)
        m1 = moments[0]
        sigma2 = moments[1] - moments[0] ** 2
        ret = []
        for k in range(1, maxn + 1):
            values = [(source[i] - m1) * (source[i + k] - m1)
                      for i in range(n - k)]
            ret.append(sum(values) / ((n - k) * sigma2))
        return np.asarray(ret)

def normalize_moments(moments, k=None):
    # TODO: add unit test
    """
    Normalizes moments using a given or computed coefficient.

    Args:
        moments (array-like): an array of the first moments
        k (scalar, callable or None): a coefficient. If None, it will be $M1$
            if only one moment is given or $\frac{M2}{M1}$. If scalar,
            this scalar will be used. If callable, it will be called as
            `k(moments)` to get the coefficient.

    Returns: tuple (ndarray, mu), where the first component is normalized
     moments, the second is the coefficient being used.
    """
    if k is None:
        try:
            mu = moments[1] / moments[0]
        except IndexError:
            mu = moments[0]
    else:
        try:
            mu = k(moments)
        except TypeError:
            mu = k
    ret = list(moments)
    for i in range(len(ret)):
        ret[i] /= pow(mu, i + 1)
    return np.asarray(ret), mu


# function to call the main analysis/synthesis functions in software/models/dftModel.py

import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import get_window
import os, sys
sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), '../models/'))
import utilFunctions as UF
import dftModel as DFT

def main(inputFile = '../../sounds/piano.wav', window = 'blackman', M = 511, N = 1024, time = .2):
    """
    inputFile: input sound file (monophonic with sampling rate of 44100)
    window: analysis window type (choice of rectangular, hanning, hamming, blackman, blackmanharris)
    M: analysis window size (odd integer value)
    N: fft size (power of two, bigger or equal than than M)
    time: time  to start analysis (in seconds)
    """

    # read input sound (monophonic with sampling rate of 44100)
    fs, x = UF.wavread(inputFile)

    # compute analysis window
    w = get_window(window, M)

    # get a fragment of the input sound of size M
    sample = int(time*fs)
    if (sample+M >= x.size or sample < 0):                          # raise error if time outside of sound
        raise ValueError("Time outside sound boundaries")
    x1 = x[sample:sample+M]

    # compute the dft of the sound fragment
    mX, pX = DFT.dftAnal(x1, w, N)

    # compute the inverse dft of the spectrum
    y = DFT.dftSynth(mX, pX, w.size)*sum(w)

    # create figure
    plt.figure(figsize=(9, 6))

    # plot the sound fragment
    plt.subplot(4,1,1)
    plt.plot(time + np.arange(M)/float(fs), x1)
    plt.axis([time, time + M/float(fs), min(x1), max(x1)])
    plt.ylabel('amplitude')
    plt.xlabel('time (sec)')
    plt.title('input sound: x')

    # plot the magnitude spectrum
    plt.subplot(4,1,2)
    plt.plot(float(fs)*np.arange(mX.size)/float(N), mX, 'r')
    plt.axis([0, fs/2.0, min(mX), max(mX)])
    plt.title ('magnitude spectrum: mX')
    plt.ylabel('amplitude (dB)')
    plt.xlabel('frequency (Hz)')
    # plot the phase spectrum
    plt.subplot(4,1,3)
    plt.plot(float(fs)*np.arange(pX.size)/float(N), pX, 'c')
    plt.axis([0, fs/2.0, min(pX), max(pX)])
    plt.title ('phase spectrum: pX')
    plt.ylabel('phase (radians)')
    plt.xlabel('frequency (Hz)')

    # plot the sound resulting from the inverse dft
    plt.subplot(4,1,4)
    plt.plot(time + np.arange(M)/float(fs), y)
    plt.axis([time, time + M/float(fs), min(y), max(y)])
    plt.ylabel('amplitude')
    plt.xlabel('time (sec)')
    plt.title('output sound: y')

    plt.tight_layout()
    plt.ion()
    plt.show()

if __name__ == "__main__":
    main()


# Generalized Lagrangian Networks | 2020
# Miles Cranmer, Sam Greydanus, Stephan Hoyer (...)

import jax
import jax.numpy as jnp
from jax import jit

@jit
def kinetic_energy(q, q_dot, m1=1, m2=1, l1=1, l2=1, g=9.8):
  (t1, t2), (w1, w2) = q, q_dot

  T1 = 0.5 * m1 * (l1 * w1)**2
  T2 = 0.5 * m2 * ((l1 * w1)**2 + (l2 * w2)**2 + 2 * l1 * l2 * w1 * w2 * jnp.cos(t1 - t2))
  T = T1 + T2
  return T

@jit
def potential_energy(q, q_dot, m1=1, m2=1, l1=1, l2=1, g=9.8):
  (t1, t2), (w1, w2) = q, q_dot

  y1 = -l1 * jnp.cos(t1)
  y2 = y1 - l2 * jnp.cos(t2)
  V = m1 * g * y1 + m2 * g * y2
  return V

# Double pendulum lagrangian
@jit
def lagrangian_fn(q, q_dot, m1=1, m2=1, l1=1, l2=1, g=9.8):
  (t1, t2), (w1, w2) = q, q_dot

  T = kinetic_energy(q, q_dot, m1=1, m2=1, l1=1, l2=1, g=9.8)
  V = potential_energy(q, q_dot, m1=1, m2=1, l1=1, l2=1, g=9.8)
  return T - V

# Double pendulum lagrangian
@jit
def hamiltonian_fn(q, q_dot, m1=1, m2=1, l1=1, l2=1, g=9.8):
  (t1, t2), (w1, w2) = q, q_dot

  T = kinetic_energy(q, q_dot, m1=1, m2=1, l1=1, l2=1, g=9.8)
  V = potential_energy(q, q_dot, m1=1, m2=1, l1=1, l2=1, g=9.8)
  return T + V

# Double pendulum dynamics via analytical forces taken from Diego's blog
@jit
def analytical_fn(state, t=0, m1=1, m2=1, l1=1, l2=1, g=9.8):
  t1, t2, w1, w2 = state
  a1 = (l2 / l1) * (m2 / (m1 + m2)) * jnp.cos(t1 - t2)
  a2 = (l1 / l2) * jnp.cos(t1 - t2)
  f1 = -(l2 / l1) * (m2 / (m1 + m2)) * (w2**2) * jnp.sin(t1 - t2) - (g / l1) * jnp.sin(t1)
  f2 = (l1 / l2) * (w1**2) * jnp.sin(t1 - t2) - (g / l2) * jnp.sin(t2)
  g1 = (f1 - a1 * f2) / (1 - a1 * a2)
  g2 = (f2 - a2 * f1) / (1 - a1 * a2)
  return jnp.stack([w1, w2, g1, g2])


# Generate set cover instances with small bandwidth
# For bandwidth 40, also solves the problem and writes the optimal value to a file

import math
import random
import itertools
import networkx as nx
import matplotlib.pyplot as plt
import numpy as np
import cplex

def generate_set_cover_constraints(n, setsize, bandwidth):
	m = n - bandwidth + 1

	matrix = np.zeros((m, n))
	inds = [[] for i in range(m)]
	coeffs = [[] for i in range(m)]

	for i in range(m):
		selected = random.sample(xrange(bandwidth), setsize)
		for j in sorted(selected):
			matrix[i][j+i] = 1
			inds[i].append("x" + str(j+i)) # assume x0 to x(n-1)
			coeffs[i].append(1)

	rows = [cplex.SparsePair(inds[i], coeffs[i]) for i in range(m)]

	return matrix, rows

def write_set_cover_mps(matrix, rows, filepath, write_opt=False):
	m = matrix.shape[0]
	n = matrix.shape[1]

	c = cplex.Cplex()

	c.objective.set_sense(c.objective.sense.minimize)

	objective = [1] * n
	lb = [0] * n
	ub = [1] * n
	coltypes = ["B"] * n
	colnames = ["x" + str(i) for i in range(n)]
	c.variables.add(obj = objective, lb = lb, ub = ub, types = coltypes, names = colnames)

	rhs = [1] * m
	senses = ["G"] * m
	rownames = ["c" + str(i) for i in range(m)]
	c.linear_constraints.add(lin_expr = rows, senses = senses, rhs = rhs, names = rownames)

	if write_opt:
		c.solve()
		f = open(filepath + ".opt", 'w')
		f.write(str(int(c.solution.get_objective_value())) + '\n')
		f.close()

	print filepath + ' generated'

	c.write(filepath + ".mps")

def generate_instance(n, setsize, bandwidth, filepath, write_opt=False):
	matrix, rows = generate_set_cover_constraints(n, setsize, bandwidth)
	write_set_cover_mps(matrix, rows, filepath, write_opt)

n_instances = 16
setsize = 30

bandwidths_opt = [40] # bandwidths for which we solve using CPLEX and write the optimal solution
bandwidths_nonopt = [50, 60]

# # Uncomment this if you do not need the optimal values
# bandwidths_opt = []
# bandwidths_nonopt = [40, 50, 60]

bandwidths = [(bd, True) for bd in bandwidths_opt] + [(bd, False) for bd in bandwidths_nonopt]

for bandwidth, write_opt in bandwidths:
	for n in [250]:
		for inst in range(n_instances):
			filepath = "sc_n" + str(n) + "_ss" + str(setsize) + "_bw" + str(bandwidth) + "_" + str(inst)
			generate_instance(n, setsize, bandwidth, filepath, write_opt)


# Fundamental of Tensor Operations - 1D

#Import libraries
import torch
import numpy as np
import pandas as pd

import matplotlib.pyplot as plt

# Plot vecotrs, please keep the parameters in the same length
# @param: Vectors = [{"vector": vector variable, "name": name of vector, "color": color of the vector on diagram}]

def plotVec(vectors):
    ax=plt.axes() #defining axis

    #loop to draw the vector
    for vec in vectors:
        ax.arrow(0,0,*vec['vector'],head_width=0.05,
        color=vec['color'],head_length=0.1)
        plt.text(*(vec['vector']+0.1),vec['name'])
    plt.ylim(-2,2)
    plt.xlim(-2,2)

## Type (.type()) and shape (.dtype) of tensor

#------------Convert a integer list with length 5 to a tensor
ints_to_tensor=torch.tensor([0,1,2,3,4])
with open('Lab1_Tensors_1D_Results.txt','a') as f:
    print('Integer to tensor: \n',file=f)
    print('Dtype of tensor after converting it to tensor',ints_to_tensor.dtype,file=f)
    print('Type of tensor after converting it to tensor',ints_to_tensor.type(),file=f)
    print('\n',file=f)
# the integer list has been converted to a long tensor. But python type is still torch

#------------Convert a float list with length 5 to a tensor
floats_to_tensor = torch.tensor([0.0, 1.0, 2.0, 3.0, 4.0])
with open('Lab1_Tensors_1D_Results.txt','a') as f:
    print('Float to tensor: \n',file=f)
    print("The dtype of tensor object after converting it to tensor: ", floats_to_tensor.dtype,file=f)
    print("The type of tensor object after converting it to tensor: ", floats_to_tensor.type(),file=f)
    print('\n',file=f)

#-------------Convert float to integer
list_floats=[0.0,1.0,2.0,3.0,4.0]
floats_int_tensor=torch.tensor(list_floats,dtype=torch.int64)
with open('Lab1_Tensors_1D_Results.txt','a') as f:
    print('Float to Integer: \n',file=f)
    print("The dtype of tensor is : ", floats_int_tensor.dtype,file=f)
    print("The type of tensor is : ", floats_int_tensor.type(),file=f)
    print('\n',file=f)

# Alternatively, using specific methods in torch, conversions can be implemented as well.

new_float_tensor=torch.FloatTensor([0,1,2,3,4])
with open('Lab1_Tensors_1D_Results.txt','a') as f:
    print('Integer to float(method): \n',file=f)
    print("The type of new_float_tensor is : ", new_float_tensor.type(),file=f)
    print('\n',file=f)

# You can also convert an existing tensor object (tensor_obj) to another tensor type

#---------------Convert the integer tensor to a float tensor:
old_int_tensor=torch.tensor([0,1,2,3,4])
new_float_tensor1=old_int_tensor.type(torch.FloatTensor)
with open('Lab1_Tensors_1D_Results.txt','a') as f:
    print('Integer to float(Another method): \n',file=f)
    print("The type of new_float_tensor1 is : ", new_float_tensor1.type(),file=f)
    print('\n',file=f)

### Tensor Object  - Size (.size()), Dimension (.ndimension()), Reshaping (.view(row,column))

# Reshaping
twoD_float_tensor = new_float_tensor.view(5, 1) # reshaping 1D to 2D matrix
with open('Lab1_Tensors_1D_Results.txt','a') as f:
    print('Size,Dimension,Reshaping \n',file=f)
    print("The size of new_float_tensor1 is : ", new_float_tensor1.size(),file=f)
    print("The dimension of new_float_tensor1 is : ", new_float_tensor1.ndimension(),file=f) #Dimension =1
    print("The original size new_float_tensor1 is : ", new_float_tensor1, file=f)
    print("The modified of new_float_tensor1 is : \n ", twoD_float_tensor,file=f)
    print('\n',file=f)

# If we have a tensor with dynamic size and wants to reshape it.
twoD_float_tensor1 = new_float_tensor.view(-1, 1)
with open('Lab1_Tensors_1D_Results.txt','a') as f:
    print('Reshaping using general and dynamic form (-1) \n',file=f)
    print("The original size new_float_tensor1 is : ", new_float_tensor1, file=f)
    print("The modified of new_float_tensor1 is : \n ", twoD_float_tensor,file=f)
    print("The modified of new_float_tensor1 using  is : \n ", twoD_float_tensor1,file=f)
    print("The size of twoD_float_tensor1 is : ", twoD_float_tensor1.size(),file=f)
    print("The dimension of twoD_float_tensor1 is : ", twoD_float_tensor1.ndimension(),file=f) #Dimension=2
    print('\n',file=f)

#----------------- Convert numpy array and pandas series to a tensor or vice-versa------------------

# -using torch.from_numpy(), <file_tensor_name>.numpy()

np_array=np.array([0.0,1.0,2.0,3.0,4.0])
new_tensor=torch.from_numpy(np_array)

back_to_numpy=new_tensor.numpy()

with open('Lab1_Tensors_1D_Results.txt','a') as f:
    print('Numpy <--> Tensor: \n',file=f)
    print("The dtype of new tensor is : ", new_tensor.dtype,file=f)
    print("The type of new tensor is : ", new_tensor.type(),file=f)
    print("The dtype of numpy from tensor is : ", back_to_numpy.dtype,file=f)
    print("The numpy array from tensor is : ", back_to_numpy,file=f)
    print('\n',file=f)

#------ Please note: back_to_numpy and new_tensor still point to numpy_array.
# As a result if we change numpy_array both back_to_numpy and new_tensor will change.

# Pandas Series can also be converted by using the numpy array that is stored in pandas_series.values.

pd_series=pd.Series([0.1,0.2,0.3,10.1])
new_tensor_pd=torch.from_numpy(pd_series.values)

with open('Lab1_Tensors_1D_Results.txt','a') as f:
    print('Pandas <--> Tensor: \n',file=f)
    print("The new tensor from numpy array: ", new_tensor_pd,file=f)
    print("The dtype of new tensor: ", new_tensor_pd.dtype,file=f)
    print("The type of new tensor: ", new_tensor_pd.type(),file=f)
    print('\n',file=f)

#Using .item() - returns of value of tensor as number, tolist() - to return a list

this_tensor=torch.tensor([0,1,2,3])
torch_to_list=this_tensor.tolist()
with open('Lab1_Tensors_1D_Results.txt','a') as f:
    print('Illustration of .item and .tolist: \n',file=f)
    print("The first item is given by: ",this_tensor[0].item(),' The first rensor value is given by: ',this_tensor[0],file=f)
    print("The first item is given by: ",this_tensor[1].item(),' The first rensor value is given by: ',this_tensor[1],file=f)
    print("The first item is given by: ",this_tensor[2].item(),' The first rensor value is given by: ',this_tensor[2],file=f)
    print("Tensor: ", this_tensor,'\nlist:',torch_to_list, file=f)

Deep Neural Networks with PyTorch/Module1/Lab1_1DTensors_Part1.py


#! /usr/bin/env python

"""
File: Lagrange_poly1.py
Copyright (c) 2016 Austin Ayers
License: MIT

Course: PHYS227
Assignment: 5.23
Date: Feb 11, 2016
Email: ayers111@mail.chapman.edu
Name: Austin Ayers
Description: Calculates Lagrange's interpolation formula
"""
import sympy as sp

def p_L(x, xp, yp):
    """
    Evaluates (5.21)
    """
    result = 0
    for i, elem_y in enumerate(yp):
        result += float(elem_y) * L_k(x, i, xp, yp)
    return result

def L_k(x, k, xp, yp):
    """
    Evaluates (5.22)
    """
    product = 1.0
    for i, elem_x in enumerate(xp):
        if(i == k):
            continue
        product *= (float((x - elem_x)) / float((xp[k] - elem_x)))
    return product

def test_p_L():
    """
    Nosetest for p_L
    """
    x = [0.2,0.4,0.6,0.8,1.0]
    y = [0.19866933079, 0.3894193423, 0.56464247339, 0.7173560909, 0.8414909878]
    for i, elem_x, in enumerate(x):
        print abs(y[i] - p_L(elem_x, x, y))
        assert(abs(y[i] - p_L(elem_x, x, y)) < 0.2)


# Author: Xinshuo Weng
# email: xinshuo.weng@gmail.com
import numpy as np

import init_paths
from math_geometry import get_2dline_from_pts
from xinshuo_miscellaneous import CHECK_EQ_NUMPY

def test_get_2dline_from_pts():
	print('check normal line')
	pts1 = [0, 1, 1]
	pts2 = [1, 0, 1]
	line = get_2dline_from_pts(pts1, pts2)
	assert CHECK_EQ_NUMPY(line, np.array([1, 1, -1]).reshape((3, 1)))

	print('check vertical line')
	pts1 = [1, 1, 1]
	pts2 = [1, 12, 1]
	line = get_2dline_from_pts(pts1, pts2)
	assert CHECK_EQ_NUMPY(line, np.array([-11, 0, 11]).reshape((3, 1)))

	print('check horizontal line')
	pts1 = [20, 0, 1]
	pts2 = [1, 0, 1]
	line = get_2dline_from_pts(pts1, pts2)
	assert CHECK_EQ_NUMPY(line, np.array([0, -19, 0]).reshape((3, 1)))

	print('check a point at infinity')
	pts1 = [0, 3, 0]
	pts2 = [1, 0, 1]
	line = get_2dline_from_pts(pts1, pts2)
	assert CHECK_EQ_NUMPY(line, np.array([3, 0, -3]).reshape((3, 1)))

	print('check line at infinity')
	pts1 = [0, 3, 0]
	pts2 = [1, 0, 0]
	line = get_2dline_from_pts(pts1, pts2)
	assert CHECK_EQ_NUMPY(line, np.array([0, 0, -3]).reshape((3, 1)))

	print('\n\nDONE! SUCCESSFUL!!\n')

if __name__ == '__main__':
	test_get_2dline_from_pts()


import numpy as np

"""
QR Factorization via Modified Gram Schmidt

Example 1: A is a complex 3x2 matrix with full column rank
>>> A = np.array([[1 + 2.1j, 2.1 + 3.1j],[2.7 + .1j, 3.1 + .2j],[4.1, 2.3j]])
>>> Q,R = gsm(A)
>>> np.linalg.norm(Q.dot(R) - A) < eps
True
>>> np.abs(inner(Q[:,0],Q[:,1])) < 2.*eps
True
>>> np.abs(inner(Q[:,1],Q[:,1]) - 1.) < 2.*eps
True

Example 2: A is a 3x3 real matrix with linearly dependent columns
>>> A = np.array([[1.,2.,3.]])
>>> A = A.T.dot(A)
>>> Q,R = gsm(A)
>>> np.linalg.norm(Q.dot(R) - A) < 8*eps
True
>>> np.abs(inner(Q[:,0],Q[:,1])) < 8*eps
True
>>> np.abs(inner(Q[:,1],Q[:,1]) - 1.) < 2*eps
True

Example 3: A is a 3x3 real matrix with one column of zeros
>>> A = np.array([[1,2,3],[0,0,0],[3,2,1]]).T+0.0
>>> Q,R = gsm(A)
>>> np.linalg.norm(Q.dot(R) - A) < 4*eps
True
>>> np.abs(inner(Q[:,0],Q[:,1])) < 2*eps
True
>>> np.abs(inner(Q[:,1],Q[:,1]) - 1.) < 2*eps
True

Note: test results may vary for Examples 2 and 3
due to the random vectors added.
"""

eps = 2**-52

def gsm(A,dbg=False):
    """modified gram-schmidt (reduced)
       takes a complex matrix of any shape and computes its
       QR factorization using the modified Gram-Schmidt factorization
       Handles the case; input matrix doesn't have full Column rank
    """
    m,n = np.shape(A)
    tp = A.dtype
    R = np.zeros((n,n),dtype=tp)
    Q = np.zeros((m,n),dtype=tp)
    V = A.copy()
    for i in range(n):
        R[i,i] = np.linalg.norm(V[:,i])
        if R[i,i] < 2*eps:
            if dbg: print("lin dep column found with i=%d" % i)
            Q[:,i] = random_orthonormal(Q,i)
        else:
            Q[:,i] = V[:,i] / R[i,i]
        for j in range(i+1,n):
            R[i,j] = inner(Q[:,i],V[:,j])
            V[:,j] -= R[i,j]*Q[:,i]
    return Q, R

def random_orthonormal(Q,i):
    """get a random unit length vector orthonormal to the
       first i-1 columns of Q
    """
    m,n=np.shape(Q)
    z = np.random.rand(m)
    v = z[:]
    for j in range(i):
        x = inner(Q[:,j],v)
        v -= x*Q[:,j]
    return v / np.linalg.norm(v)

def inner(v,w):
    """return the inner product of two vectors
       using the convention of conjugating the first argument
    """
    return v.conj().dot(w)

def bslv(R,c):
    """
    R should be upper triangular mxn with nonzero diagonal entries
    and c mx1.  Solves Rx = c by back substitution
    """
    tp = R.dtype
    _,n = shape(R)
    x = zeros(n,dtype=tp)
    for i in range(n-1,-1,-1):
        x[i] = (c[i]-R[i,i+1:].dot(x[i+1:])) / R[i,i]
    return x

def slv(A,b):
    """
    Solve linear system Ax = b
    """
    Q,R = gsm(A)
    c = Q.T.dot(b)
    x = bslv(R,c)
    return x

if __name__ == "__main__":
    import doctest
    doctest.testmod()


# -*- coding: utf-8 -*-
"""
Created on Tue Jul  3 14:55:08 2018

@author: SilverDoe
"""

'''==== Linear algebra====

SciPy.linalg vs NumPy.linalg
============================
A scipy.linalg contains all the functions that are in numpy.linalg. Additionally, scipy.
linalg also has some other advanced functions that are not in numpy.linalg. Another advantage
of using scipy.linalg over numpy.linalg is that it is always compiled with BLAS/LAPACK support,
while for NumPy this is optional. Therefore, the SciPy version might be faster depending on how
NumPy was installed.

https://docs.scipy.org/doc/scipy/reference/tutorial/linalg.html
'''
#============= Solving lenear Equations =======================================

#importing the scipy and numpy packages
from scipy import linalg
import numpy as np

#Declaring the numpy arrays
a = np.array([[3, 2, 0], [1, -1, 0], [0, 5, 1]])
b = np.array([2, 4, -1])

#Passing the values to the solve function
x = linalg.solve(a, b)

#printing the result array
print(x)

#========== Finding Determinanat ==============================================

#importing the scipy and numpy packages
from scipy import linalg
import numpy as np

#Declaring the numpy array
A = np.array([[1,2],[3,4]])

#Passing the values to the det function
x = linalg.det(A)

#printing the result
print(x)

#======= Finding Eigen values and Eigen vectors ===============================

#importing the scipy and numpy packages
from scipy import linalg
import numpy as np

#Declaring the numpy array
A = np.array([[1,2],[3,4]])

#Passing the values to the eig function
l, v = linalg.eig(A)

#printing the result for eigen values
print(l)

#printing the result for eigen vectors
print(v)

#==================== SVD =====================================================

'''A Singular Value Decomposition (SVD) can be thought of as an extension of the eigenvalue
problem to matrices that are not square.

The scipy.linalg.svd factorizes the matrix ‘a’ into two unitary matrices ‘U’ and ‘Vh’ and a
 1-D array ‘s’ of singular values (real, non-negative) such that a == U*S*Vh, where ‘S’ is a
 suitably shaped matrix of zeros with the main diagonal ‘s’.

'''

#importing the scipy and numpy packages
from scipy import linalg
import numpy as np

#Declaring the numpy array
a = np.random.randn(3, 2) + 1.j*np.random.randn(3, 2)

#Passing the values to the eig function
U, s, Vh = linalg.svd(a)

# printing the result
print(U, Vh, s)

#==============================================================================


import numpy

def backward_substitution(U, b):
    """Upper triangular matrix `U` and right hand side vector `b`.
    """
    n = b.size
    x = ones_like(b)
    for k in range(n)[::-1]:
        q = 0.
        for j in range(k+1, n):
            q = q + U[k, j]*x[j]
        x[k] = (b[k] - q)/U[k, k]
    return x

def forward_substitution(L, b):
    """Lower triangular matrix `L` and right hand side vector `b`.
    """
    x = ones_like(b)
    for k in range(n):
        q = 0.
        for j in range(k):
            q = q + L[k, j]*x[j]
        x[k] = (b[k] - q)/L[k, k]
    return x


"""
Tests related to the measure module.
"""

import pytest
import numpy as np
import msf_2022

def test_calculate_distance() -> None:

    r1 = np.array([0, 2, 0])
    r2 = np.array([0, 1, 0])

    expected_distance = 1.0

    calculated_distance = msf_2022.calculate_distance(r1, r2)

    assert calculated_distance == expected_distance, "Unexpected calculated distance"

@pytest.mark.parametrize(
    "p1, p2, p3, expected_angle",
    [
        (
            np.array([np.sqrt(2) / 2, np.sqrt(2) / 2, 0]),
            np.array([0, 0, 0]),
            np.array([1, 0, 0]),
            45,
        ),
        (np.array([0, 0, -1]), np.array([0, 1, 0]), np.array([1, 0, 0]), 60),
        (
            np.array([np.sqrt(3) / 2, (1 / 2), 0]),
            np.array([0, 0, 0]),
            np.array([1, 0, 0]),
            30,
        ),
    ],
)
def test_calculate_angle_many(p1, p2, p3, expected_angle):

    calculated_angle = msf_2022.calculate_angle(p1, p2, p3, degrees=True)

    assert expected_angle == pytest.approx(
        calculated_angle
    ), f"{calculated_angle} {expected_angle}"


# -*- coding: utf-8 -*-
"""Linear_Regerssion.ipynb

Automatically generated by Colaboratory.

Original file is located at
    https://colab.research.google.com/github/Abdokarawia/Linear-Regerssion/blob/main/Linear_Regerssion.ipynb
"""

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

EDS = pd.read_csv('/content/FuelConsumptionCo2.csv')
EDS.head()   # Showing a sample of the dataset

EDS.describe()

sns.pairplot(EDS , aspect=1 , height=4)
plt.show()

DS = EDS [['ENGINESIZE', 'CYLINDERS', 'FUELCONSUMPTION_COMB',  'FUELCONSUMPTION_CITY', 'CO2EMISSIONS' , 'FUELCONSUMPTION_COMB_MPG' ]]
DS.head(9)

sns.pairplot(data =DS , kind='scatter', height=4,   x_vars=['ENGINESIZE', 'CYLINDERS', 'FUELCONSUMPTION_COMB' , "FUELCONSUMPTION_COMB_MPG"], y_vars="CO2EMISSIONS" )
plt.show()

sns.boxplot(DS.CO2EMISSIONS ,color="lightblue")
plt.show()

sns.heatmap(DS.corr(), cmap="YlGnBu")
plt.show()

# First Way
mask  = np.random.rand(len(DS)) < 0.75
train = DS[mask]
test  = DS [~mask]

# Second Way
# from sklearn.model_selection import train_test_split
# X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

sns.pairplot(data =train , kind='scatter', height=4, aspect=1.2 , x_vars=['ENGINESIZE', 'CYLINDERS', 'FUELCONSUMPTION_COMB'], y_vars="CO2EMISSIONS" )
sns.pairplot(data =test , kind='scatter', height=4, aspect=1.2 , x_vars=['ENGINESIZE', 'CYLINDERS', 'FUELCONSUMPTION_COMB'], y_vars="CO2EMISSIONS" )
plt.show()

from sklearn.linear_model import  LinearRegression
LR = LinearRegression()
x_train = np.asarray(train[["ENGINESIZE"]])
y_train = np.asarray(train[["CO2EMISSIONS"]])
x_test  = np.asarray(test[["ENGINESIZE"]])
y_test  = np.asarray(test[["CO2EMISSIONS"]])
LR.fit(x_train , y_train)
intercept = LR.intercept_
coef = LR.coef_

plt.scatter(x_train, y_train , c="blue")
plt.plot(x_train, LR.predict(x_train)  , c="red")
predict_test = LR.predict(x_test)

from sklearn.metrics import r2_score
MAE = np.mean(np.abs(predict_test - y_test))
MSE = np.mean(np.abs(predict_test - y_test) **2 )
R2 = r2_score(y_test , predict_test)
print("Mean absolute error: %.2f" % MAE)
print("Residual sum of squares (MSE): %.2f" % MSE)
print("R2-score: %.4f" % R2 )


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

# # Método de la secante
# J.J
# ---
# Está dado por las iteraciones
# \begin{equation}
# x_{i+1} = x_{i} - \frac{f(x_{i})}{d_{i}},
# \end{equation}
# con
# \begin{equation}
# d_{i} = \frac{f(x_{i})-f(x_{i-1})}{x_{i} - x_{i-1}}.
# \end{equation}

# Ejemplo: $f(x) = x^{2} + 3x +1$

# In[1]:

import numpy as np
import matplotlib.pyplot as plt

# In[2]:

def f(x):
    f = x**2 + 3*x + 1
    return f

# In[3]:

X = np.linspace(-3, 1, 100)
plt.plot(X, f(X))

# In[4]:

e = 0.0001 #error
maxit = 1000 #iteraciones máximas

# In[5]:

def Secante(x0, x1, func = f, error = e, iterations = maxit):
    it = 0
    while it < maxit:
        it += 1
        x = x1 - ((x1-x0)/(f(x1)-f(x0)))*f(x1)
        if abs(f(x)) > e:
            x0 = x1
            x1 = x
        else:
            break
    return x

# In[6]:

sol1 = Secante(-3.,-2.)
sol2 = Secante(-1.,0.)
print(sol1)
print(sol2)

# In[7]:

X = np.linspace(-3, 1, 100)
plt.plot(X, f(X))
plt.plot(sol1,f(sol1),'ro')
plt.plot(sol2,f(sol2),'ro')
plt.show()

# In[ ]:


#from numpy import zeros, linspace, pi, cos
import numpy as np
import matplotlib.pyplot as plt

def osc_Heun(X_0, omega, dt, T):
    N_t = int(round(T/dt))
    u = np.zeros(N_t+1)
    v = np.zeros(N_t+1)
    t = np.linspace(0, N_t*dt, N_t+1)

    # Initial condition
    u[0] = X_0
    v[0] = 0

    # Step equations forward in time
    for n in range(N_t):
        u_star = u[n] + dt*v[n]
        v_star = v[n] - dt*omega**2*u[n]
        u[n+1] = u[n] + 0.5*dt*(v[n] + v_star)
        v[n+1] = v[n] - 0.5*dt*omega**2*(u[n] + u_star)
    return u, v, t

def demo():
    omega = 2
    P = 2*np.pi/omega
    dt = P/20
    T = 10*P
    X_0 = 2
    u, v, t = osc_Heun(X_0, omega, dt, T)

    fig = plt.figure()
    l1, l2 = plt.plot(t, u, 'b-', t, X_0*np.cos(omega*t), 'r--')
    fig.legend((l1, l2), ('numerical', 'exact'), 'upper left')
    plt.xlabel('t')
    plt.savefig('tmp.pdf'); plt.savefig('tmp.png')
    plt.show()

if __name__ == '__main__':
    demo()


# Code is from Osvaldo Martin et al,
# "Bayesian Modeling and Comptuation In Python"
# https://github.com/aloctavodia/BMCP/blob/master/Code/chp_3_5/splines.py

import superimport

import numpy as np
import matplotlib.pyplot as plt
from scipy import stats
from patsy import bs, dmatrix
import pyprobml_utils as pml

x = np.linspace(0., 1., 500)
knots = [0.25, 0.5, 0.75]

B0 = dmatrix("bs(x, knots=knots, degree=0, include_intercept=True) - 1", {"x": x, "knots":knots})
B1 = dmatrix("bs(x, knots=knots, degree=1, include_intercept=True) - 1", {"x": x, "knots":knots})
B3 = dmatrix("bs(x, knots=knots, degree=3, include_intercept=True) - 1", {"x": x, "knots":knots})

np.random.seed(1563)
_, ax = plt.subplots(2, 3, figsize=(12, 6), sharex=True,
                     sharey='row')
for idx, (B, title) in enumerate(zip((B0, B1, B3),
                                     ("Piecewise constant", "Piecewise linear", "Cubic spline"))):
    # plot spline basis functions
    for i in range(B.shape[1]):
        ax[0, idx].plot(x, B[:, i], color=str(1-(i+1)/B.shape[1]), lw=2, ls="--")
    # we generate some positive random coefficients (there is nothing wrong with negative values)
    β = np.abs(np.random.normal(0, 1, size=B.shape[1]))
    # plot spline basis functions scaled by its β
    for i in range(B.shape[1]):
        ax[1, idx].plot(x, B[:, i]*β[i],
                        color=str(1-(i+1)/B.shape[1]), lw=2, ls="--")
    # plot the sum of the basis functions
    ax[1, idx].plot(x, np.dot(B, β), color='k', lw=3)
    # plot the knots
    ax[0, idx].plot(knots, np.zeros_like(knots), "ko")
    ax[1, idx].plot(knots, np.zeros_like(knots), "ko")
    ax[0, idx].set_title(title)

pml.savefig('splines_weighted.pdf', dpi=300)
plt.show()


##################################################################################################################
#   ADAPTIVE SUPERRESOLUTION WAVELET (SUPERLET) TRANSFORM
#
#   ORIGINAL AUTHOR:         Harald Bârzan
#   PYTHON TRANSLATION:     Manuel Lima
#   DATE:           June 2021
#   DESCRIPTION:
#
#   Computes the adaptive superresolution wavelet (superlet) transform on
#   input data to produce a time-frequency representation. For each
#   frequency of interest, the closest integer order from the order
#   interval will be chosen to produce each superlet. A superlet is a set
#   of wavelets with the same center frequency but different number of
#   cycles.
#
#   REFERENCE:
#
#   Superlets: time-frequency super-resolution using wavelet sets
#   Moca, V.V., Nagy-Dãbâcan, A., Bârzan, H., Mure?an, R.C.
#   https://www.biorxiv.org/content/10.1101/583732v1.full
#
#   NOTES:
#
#   If the input data consists of multiple buffers, a wavelet spectrum will
#   be computed for each of the buffers and averaged to produce the final
#   result.
#   If the order parameter (ord) is empty, this function will return the
#   standard CWT (one wavelet per frequency of interest).
#
#   INPUT:
#   > input         - input data as numpy array with shape (n_buffers, n_samples)
#   > Fs            - sampling frequency in Hz
#   > F             - frequency-of-interest numpy array with shape (n_frequencies)
#   > Ncyc          - number of initial wavelet cycles (default: 3)
#   > ord           - two-element integer tuple (min_ord, max_ord) (default: None)
#   > mult          - specifies the use of multiplicative superresolution
#                     (False - additive, True - multiplicative)
#
#   OUTPUT:
#   > wtresult      - superlet spectrum as numpy array with shape (n_frequencies, n_samples)
##################################################################################################################
import numba as nb
import numpy as np

# compute the complex wavelet coefficients for the desired time point t, bandwidth bw and center frequency cf
@nb.jit(nb.complex128(nb.float64, nb.float64, nb.float64), nopython=True, fastmath=True)
def bw_cf(t, bw, cf):
    cnorm = 1.0 / (bw * np.sqrt(2 * np.pi))
    exp1 = cnorm * np.exp(-(t**2) / (2 * bw**2))
    return np.exp(2j * np.pi * cf * t) * exp1

# compute the gaussian coefficient for the desired time point t and standard deviation sd
@nb.jit(nb.float64(nb.float64, nb.float64), nopython=True, fastmath=True)
def gauss(t, sd):
    cnorm = 1 / (sd * np.sqrt(2 * np.pi))
    res = cnorm * np.exp(-(t ** 2) / (2 * sd ** 2))
    return res

# computes the complex Morlet wavelet for the desired center frequency Fc with Nc cycles, with a sampling frequency Fs.
@nb.jit(nb.complex128[:](nb.float64, nb.int64, nb.float64), nopython=True, fastmath=True)
def cxmorlet(Fc, Nc, Fs):
    #we want to have the last peak at 2.5 SD
    sd = (Nc / 2) * (1 / Fc) / 2.5
    wl = int(2 * np.floor((6 * sd * Fs) / 2) + 1)
    w = np.zeros(wl, dtype=np.complex128)
    gi = 0
    off = int(wl / 2)

    for i in range(0,wl):
        t = (i - 1 - off) / Fs
        w[i] = bw_cf(t, sd, Fc)
        gi = gi + gauss(t, sd)

    w = w / gi
    return w

def aslt(input, Fs, F, Ncyc, ord=None, mult=True):
    if (ord is None):
        order_ls = np.ones(F.shape[0], dtype=np.int64)
    else:
        order_ls = np.fix(np.linspace(ord[0], ord[1], F.shape[0])).astype(int)

    # get the input size
    Nbuffers, Npoints = input.shape

    padding = 0

    wavelets = [[None for o in range(0,np.max(ord))] for f in range(0,F.shape[0])]

    # initialize wavelet sets for either additive or multiplicative superresolution
    if (mult):
        for i_freq in range(0,F.shape[0]):
            for i_ord in range(0,order_ls[i_freq]):
                # each new wavelet has Ncyc extra cycles (multiplicative superresolution)
                wavelets[i_freq][i_ord] = cxmorlet(F[i_freq], Ncyc * i_ord + 1, Fs)

                # the margin will be the half-size of the largest wavelet
                padding = np.max([padding, int(wavelets[i_freq][i_ord].shape[0] / 2.0)])
    else:
        for i_freq in range(0,F.shape[0]):
            for i_ord in range(0,order_ls[i_freq]):
                # each new wavelet has an extra cycle (additive superresolution)
                wavelets[i_freq][i_ord] = cxmorlet(F[i_freq], Ncyc + i_ord + 1, Fs)

                # the margin will be the half-size of the largest wavelet
                padding = np.max([padding, int(wavelets[i_freq][i_ord].shape[0] / 2.0)])

    # the zero-padded buffer
    buffer = np.zeros(Npoints + 2 * padding)

    # the output scalogram
    wtresult = np.zeros([F.shape[0], Npoints])

    # convenience indexers for the zero-padded buffer
    bufbegin = padding
    bufend = padding + Npoints

    # loop over the input buffers
    for i_buf in range(0, Nbuffers):
        for i_freq in range(0, F.shape[0]):

            # pooling buffer, starts with 1 because we're doing geometric mean
            temp = np.ones(Npoints)

            # fill the central part of the buffer with input data
            buffer[bufbegin:bufend] = input[i_buf, :]

            # compute the convolution of the buffer with each wavelet in the current set
            for i_ord in nb.prange(0, order_ls[i_freq]):
                # restricted convolution (input size == output size)
                tempcx = np.convolve(buffer, wavelets[i_freq][i_ord], mode='same')

                # accumulate the magnitude (times 2 to get the full spectral energy
                temp = temp * (2 * np.abs(tempcx[bufbegin:bufend]) ** 2).T

            # compute the power of the geometric mean
            root = 1 / order_ls[i_freq]
            temp = temp ** root

            # accumulate the current FOI to the result spectrum
            wtresult[i_freq, :] = wtresult[i_freq, :] + temp

    # scale the output by the number of input buffers
    wtresult = wtresult / Nbuffers

    return wtresult


import numpy as np
import scipy.stats as sp

__all__ = ["linear_regression"]

def _lr_statistics(independent_vars, dependent_var, coefficients):
    """Computes t-test and confidence intervals for linear regression."""
    n_groups = independent_vars.shape[0] - 1
    deg_of_freedom = dependent_var.size - n_groups - 1

    sum_squared_total = np.var(dependent_var) * dependent_var.size
    sum_squared_error = np.square(dependent_var
                                  - independent_vars.T @ coefficients).sum()
    sum_squared_residual = sum_squared_total - sum_squared_error

    mean_squared_residual = sum_squared_residual / n_groups
    mean_squared_error = sum_squared_error / deg_of_freedom

    f_statistic = mean_squared_residual / mean_squared_error
    f_p_value = sp.f.sf(f_statistic, n_groups, deg_of_freedom)

    # R-Squared
    r_squared = sum_squared_residual / sum_squared_total
    r_squared_adjust = (1 - mean_squared_error
                        * (dependent_var.size - 1) / sum_squared_total)

    # T-Tests
    estimator = np.linalg.inv(independent_vars @ independent_vars.T)
    estimator *= mean_squared_error
    standard_errors = np.sqrt(np.diag(estimator))

    # Use 2-tailed tests
    t_value = coefficients / standard_errors
    t_p_value = sp.t.sf(np.abs(t_value), deg_of_freedom) * 2
    coefficient_statistics = list(zip(t_value, t_p_value))

    # 95th Percentile confidence intervals
    scalar = sp.t.isf(0.025, deg_of_freedom)
    confidence_interval = np.array([coefficients - scalar * standard_errors,
                                    coefficients + scalar * standard_errors])

    statistics = {
        'DF': (n_groups, deg_of_freedom),
        'F_value': f_statistic, 'P_value': f_p_value,
        'Coefficient T-Tests': coefficient_statistics,
        'RSq': r_squared, 'RSq_adj': r_squared_adjust,
        '95th CI': confidence_interval}

    return statistics

def linear_regression(independent_vars, dependent_var):
    """Performs a least-squares linear regression.

    Args:
        independent_vars: [n_vars x n_observations] array of independent variables
        dependent_var:  dependent variable [n_observations]

    Returns:
        regression_dict: Dictionary with regression parameters and statistics

    Example:
        result = linear_regression(np.vstack((independent1, independent2, ...)),
                                    dependent_y)

    Note:
        Missing data (marked by nan) is removed from all data.
    """
    # Clean the data if necessary
    valid_mask_dependent = ~np.isnan(dependent_var)
    valid_mask_independent = ~np.isnan(independent_vars)
    valid_mask = valid_mask_dependent & np.all(valid_mask_independent, axis=0)

    independent_vars = independent_vars[:, valid_mask]
    dependent_var = dependent_var[valid_mask]

    # Remove Mean and Standard Deviation
    dep_mean = dependent_var.mean()
    dep_std = dependent_var.std(ddof=1)

    idep_mean = independent_vars.mean(axis=1)
    idep_std = independent_vars.std(axis=1, ddof=1)

    # Centered - Scaled Variables
    new_dependent = (dependent_var - dep_mean) / dep_std
    new_independent = (independent_vars - idep_mean[:, None]) / idep_std[:, None]

    # "Beta" (Standardized) Coefficients
    coeffs = (np.linalg.pinv(new_independent.T) @ new_dependent[:, None]).squeeze()
    coeffs = np.atleast_1d(coeffs)

    # Regression Coefficients
    ratio = dep_std / idep_std
    regression_coefficients = np.ones((coeffs.size + 1))
    regression_coefficients[1:] = ratio * coeffs
    regression_coefficients[0] = dep_mean - (regression_coefficients[1:] * idep_mean).sum()

    output = {'Regression Coefficients': regression_coefficients,
              'Standard Coefficients': np.concatenate(([0], coeffs))}

    # Account for the intercept for statistics
    independent_vars = np.vstack((np.ones_like(dependent_var), independent_vars))
    statistics = _lr_statistics(independent_vars, dependent_var,
                                regression_coefficients)
    output.update(statistics)

    return output


#
# @Author: kuroitu (2020)
# @email: skuroitu@gmail.com
#

import numpy as np

from ..dual import *
from .const import pi

##########
# 双曲線関数 hyperbolical functions
#######
def sinh(obj):
    obj = to_dual(obj)
    return Dual(np.sinh(obj.re), obj.im * np.cosh(obj.re))

def cosh(obj):
    obj = to_dual(obj)
    return Dual(np.cosh(obj.re), obj.im * np.sinh(obj.re))

def tanh(obj):
    obj = to_dual(obj)
    return Dual(np.tanh(obj.re), obj.im / np.cosh(obj.re) ** 2)

def arcsinh(obj):
    obj = to_dual(obj)
    return Dual(np.arcsinh(obj.re), obj.im / np.sqrt(1 + obj.re ** 2))

def arccosh(obj):
    obj = to_dual(obj)
    return Dual(np.arccosh(obj.re), obj.im / np.sqrt(obj.re ** 2 - 1))

def arctanh(obj):
    obj = to_dual(obj)
    return Dual(np.arctanh(obj.re), obj.im / (1 - obj.re ** 2))

def csch(obj, switch=True):
    if switch:
        obj = to_dual(obj)
        return Dual(1 / np.sinh(obj.re),
                    - obj.im / (np.tanh(obj.re) * np.sinh(obj.re)))
    return 1 / sinh(obj)

def sech(obj, s=True):
    if s:
        obj = to_dual(obj)
        return Dual(1 / np.cosh(obj.re),
                    - obj.im * np.tanh(obj.re) / np.cosh(obj.re))
    return 1 / cosh(obj)

def coth(obj, s=True):
    if s:
        obj = to_dual(obj)
        return Dual(1 / np.tanh(obj.re),
                    - obj.im / np.sinh(obj.re) ** 2)
    return 1 / tanh(obj)

def arccsch(obj, s=True):
    if s:
        obj = to_dual(obj)
        return Dual(np.arcsinh(1 / obj.re),
                    - obj.im/(obj.re ** 2 * np.sqrt(1 + 1 / obj.re ** 2)))
    return arcsinh(1 / obj)

def arcsech(obj, s=True):
    obj = to_dual(obj)
    return Dual(np.arccosh(1 / obj.re),
                - obj.im / (obj.re ** 2 * np.sqrt(1 / obj.re - 1)
                         * np.sqrt(1 / obj.re + 1)))

def arccoth(obj):
    obj = to_dual(obj)
    return Dual(np.arctanh(1 / obj.re), obj.im / (1 - obj.re ** 2))

def sinch(obj, norm=True):
    if norm:
        obj = to_dual(obj)
        return Dual(np.sinh(obj.re * pi) / (obj.re * pi),
                    obj.im * (obj.re * np.cosh(obj.re * pi)
                              - np.sinh(obj.re * pi) / pi) / obj.re ** 2)
    else:
        obj = to_dual(obj)
        return Dual(np.sinh(obj.re) / obj.re,
                    obj.im * (obj.re * np.cosh(obj.re)
                              - np.sinh(obj.re)) / obj.re ** 2)


from statistics import mean
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import style
style.use('fivethirtyeight')

xs = np.array([1,2,3,4,5,6], dtype = np.float64)
ys = np.array([5,4,6,5,6,7], dtype = np.float64)

def best_fit_slope_and_intercept(xs, ys):
	m = (  ((mean(xs)*mean(ys)) - mean(xs*ys)) /
		((mean(xs)*mean(xs)) - mean(xs*xs)) )

	b = ( mean(ys) -(m* mean(xs)) )
	return m, b

m, b = best_fit_slope_and_intercept(xs, ys)

regression_line = [(m*x)+b for x in xs]

predict_x = 1.5
predict_y = (m*predict_x + b)

#accuracy =

plt.scatter(xs, ys)
plt.scatter(predict_x, predict_y, color='g')
plt.plot(xs, regression_line)
plt.show()


import numpy as np

def covarianceEllipse(cov_mat,img_dim = (1,1), center_point = (0,0)):
    eigenvalues, eigenvectors = np.linalg.eig(cov_mat)
    theta = np.linspace(0, 2*np.pi, 1000)
    ellipse = (np.sqrt(eigenvalues[None,:]) * eigenvectors) @ [np.sin(theta), np.cos(theta)]
    ellipse[0,:] = ellipse[0,:]*img_dim[0]
    ellipse[1,:] = ellipse[1,:]*img_dim[1]
    print(center_point[0],center_point[1],"\n---------------------\n")
    for i in range(ellipse.shape[1]):
        ellipse[0,i] += center_point[0]
        ellipse[1,i] += center_point[1]

    return ellipse


# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# 2021 Rex McAllister
# https://downloads.rene-schwarz.com/download/M001-Keplerian_Orbit_Elements_to_Cartesian_State_Vectors.pdf
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Imports
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

from tletools import TLE
import matplotlib.pyplot as plt
import numpy as np
import math
from math import *
import sys

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Constants
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

gravParam = 3.986004418 * (10 ** 14)
pi = math.pi
toRad = pi / 180
toDec = 180 / pi

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Variables
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# TLE to Keplerian Elements
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

# converts the longitude of the ascending node from TLE degrees to radians
def calc_lan(tle):
    lan = (tle.raan * toRad)
    return lan

# converts the argument of perigee from TLE degrees to radians
def calc_argp(tle):
    argp = (tle.argp * toRad)
    return argp

# converts the inclination from TLE degrees to radians
def calc_inc(tle):
    inc = (tle.inc * toRad)
    return inc

# returns the native format of eccentricity from TLE
def calc_eccentricity(tle):
    ecc = (tle.ecc)
    return ecc

# converts the mean motion from TLE rev/day to rad/s
def calc_n(tle):
    n = float(tle.n) * ((1.0/86400.0) * (2.0 * pi))
    return n

# calculates the length of the semimajor axis in kilometers
def calc_sma(tle):
    n = calc_n(tle)
    sma = (gravParam / (n ** 2)) ** (1.0/3.0)
    return sma

# converts the mean anomaly from TLE degrees to radians
def calc_M(tle):
    M = tle.M * toRad
    return M

# calculates the eccentric anomaly (rad) using a Newton-Rhapson setup
def calc_E(tle):
    M = calc_M(tle)
    ecc = calc_eccentricity(tle)
    E = M
    nextE = E - ((E - (ecc * sin(E - M))) / (1 - ecc * cos(E)))
    while (abs((nextE - E) / nextE) > 1e-14):
        E = nextE
        # both versions of the equation yield the same answer
        # nextE = (((M) - (ecc * (E * math.cos(E) - math.sin(E)))) / (1 - ecc * math.cos(E)))
        nextE = E - ((E - (ecc * sin(E)) - M) / (1 - (ecc * cos(E))))
    return E

# calculates the true anomaly (rad)
def calc_truea(tle):
    M = calc_M(tle)
    E = calc_E(tle)
    ecc = calc_eccentricity(tle)

    truea = 2 * atan2(sqrt(1 + ecc) * sin(E / 2), sqrt(1 - ecc) * cos(E / 2))

    return truea

def calc_truea_deltaT(tle, deltaTSeconds) :
    M = calc_M(tle)
    ecc = calc_eccentricity(tle)
    n = calc_n(tle)
    M = M + (n * deltaTSeconds)
    # same as calc_E except is propogates the mean anomaly forward in time
    E = M
    nextE = E - ((E - (ecc * sin(E - M))) / (1 - ecc * cos(E)))
    while (abs((nextE - E) / nextE) > 1e-14):
        E = nextE
        # both versions of the equation yield the same answer
        # nextE = (((M) - (ecc * (E * math.cos(E) - math.sin(E)))) / (1 - ecc * math.cos(E)))
        nextE = E - ((E - (ecc * sin(E)) - M) / (1 - (ecc * cos(E))))
    v = 2 * atan2(sqrt(1 + ecc) * sin(E / 2), sqrt(1 - ecc) * cos(E / 2))
    return v

# creates an array of the value of true anomaly for a period of time over the orbit
def calc_truea_time(tle, increment, numSeconds):
    E = calc_E(tle)
    M = calc_M(tle)
    ecc = calc_eccentricity(tle)
    n = calc_n(tle)
    epochX = []
    trueaY = []

    def my_range(start, end, step):
        while start <= end:
            yield start
            start += step
    for i in my_range(0, numSeconds, 60):

        epochX.append(i / 60.0)
        trueaY.append(calc_truea_deltaT(tle, i))
    return epochX, trueaY

# returns a dictionary of calculated orbital elements for a TLE
def tleToKepler(tle):

    lan = calc_lan(tle)           # longitude ascending node
    argp = calc_argp(tle)         # argument periapsis
    inc = calc_inc(tle)           # inclination
    ecc = calc_eccentricity(tle)  # eccentricity
    n = calc_n(tle)               # mean motion
    M = calc_M(tle)               # mean anomaly
    a = calc_sma(tle)             # semimajor axis
    E = calc_E(tle)               # eccentric anomaly
    v = calc_truea(tle)           # true anomaly

    return lan, argp, inc, ecc, n, M, a, E, v


import numpy as np
import numpy.linalg as la

def GOE(N):
	H1 = np.triu(np.random.normal(scale=1,size=(N,N)))
	H = H1+H1.T
	H[range(N),range(N)] /=np.sqrt(2)
	return H

def GUE(N):
	H0 = np.random.normal(scale=np.sqrt(0.5),size=(N,N))
	H1 = np.triu(H0,k=1)
	H2 = np.tril(H0,k=-1)
	H3 = np.diag(np.diag(H0))*np.sqrt(2)
	H = H1+H1.T+np.complex(0,1)*H2+np.complex(0,-1)*H2.T+H3;
	return H

def Wigner_Real(N):
	H1 = np.triu(np.random.normal(scale=1,size=(N,N)))
	H = H1+H1.T
	H[range(N),range(N)] /=2
	return H

def Wigner_Complex(N,alpha):
	H0 = np.random.normal(scale=np.sqrt(1),size=(N,N))
	H1 = np.triu(H0,k=1)
	H2 = np.tril(H0,k=-1)
	H3 = np.diag(np.diag(H0))
	H = np.sqrt(alpha)*(H1+H1.T)+np.sqrt(1-alpha)*(np.complex(0,1)*H2+np.complex(0,-1)*H2.T)+H3;
	return H

def space(H):
	N = H.shape[0]
	eigs = np.real(la.eigvalsh(H))
	eigs.sort()
	space_H = eigs[1:]-eigs[:-1]
	return space_H

def mean_space(N, sample = 200, mtype = 'GOE'):
	m_space = np.zeros(N-1)
	for i in range(sample):
		if mtype == 'GOE':
			m_space += space(GOE(N))
		if mtype == 'GUE':
			m_space += space(GUE(N))
	m_space/=sample
	return m_space

def multi_space(N, sample = 200, mtype = 'GOE'):
	m_space = np.zeros([sample,N-1])
	for i in range(sample):
		if mtype == 'GOE':
			m_space[i] = space(GOE(N))
		if mtype == 'GUE':
			m_space[i] = space(GUE(N))
	return m_space


import numpy as np

def f(x):
    y = 1.2 * x + 2
    return y

def mean_absolute_eror(f, points):
    summed = 0.0
    m = len(points)
    for point in points:
        x, y = point
        yp = f(x)
        summed += np.abs(yp - y)
    return summed / m

def mean_squared_error(f, points):
    summed = 0.0
    m = len(points)
    for point in points:
        x, y = point
        yp = f(x)
        summed += ((yp - y)**2.0)
    return summed / (2.0 * m)

if __name__ == '__main__':

    test_points = [(2, -2), (5, 6), (-4, -4), (-7, 1), (8, 14)]
    mae = mean_absolute_eror(f, test_points)
    mse = mean_squared_error(f, test_points)
    print("MAE", mae)
    print("MSE", mse)


# A x = b
# 1. Elimination
# 2. Back Substitution

import numpy as np

A = np.array([[3,-2,5,0],
              [4,5,8,1],
              [1,1,2,1],
              [2,7,6,5]], float)

b = np.array([2,4,5,7], float)
n = len(b)

# Solution vector
x = np.zeros(n, float)

# 1. Elimination

for k in range(n-1): # to index fixed rows and cols
    for i in range(k+1,n):

        # if the element is already 0, skip to next i
        if A[i,k] == 0:
            continue
        factor = A[k,k] / A[i,k]

        for j in range(k,n):
            A[i,j] = A[k,j] - A[i,j]*factor

        b[i] = b[k] - b[i]*factor

# 2. Back Substitution

# starting from last row
x[n-1] = b[n-1] / A[n-1, n-1]

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

print('The Solution of the system:')

for i in range(n):
    print('{}. {:.2f}'.format(i, x[i]))


import numpy as np

def reimp():
  """Reimport this module"""
  import importlib
  importlib.reload('ch01.startr')

def pv_f(fv, r, n):
  """Objective: estimate present value
  fv  : = future value
  r   : = rate of discount
  n   : = num of iterations (usually num of years, num of months etc)
                    fv
  formula : pv =  --------
                   (1 + r) ^ n

  """
  pv = 0
  iCount = 0
  for cash in fv:
    pv = pv + cash / (1 + r) ** iCount
    iCount = iCount + 1

  # you can use enumeration too
  pv2 = 0
  for i2, cashFlow in enumerate(fv):
    pv2 = pv2 + cashFlow / (1 + r) ** i2

  return (pv, pv2)

def np_itr_a() :
  """ create an array using numpy and itrate"""
  cashFlows = np.array([1, 20])
  for cash in cashFlows:
    print(cash + 100)

def calc():
  fv = [-100,-30, 10, 40,50, 45,20]
  rate = 3.5 / 100
  cycles = 100

  pv1, pv2 = pv_f(fv, rate, cycles)
  print("Present value at rate=", rate, " where fv=", fv )
  print("      -- is 1:",pv1)
  print("      -- is 2:",pv2)

  pv3, _ = pv_f(fv, rate, cycles)
  print("Present value at rate=", rate, " where fv=", fv )
  print("      -- is 1:",pv3)


import numpy as np
from matplotlib import pyplot as plt
import sys
X = np.array([
    [-2,4,-1],
    [4,1,-1],
    [1, 6, -1],
    [2, 4, -1],
    [6, 2, -1],

])
#X1 = np.array([
#    [-2,4],
#    [4, 1],
#    [1, 6],
#    [2, 4],
#    [6, 2]
#
#])
y = np.array([-1,-1,1,1,1])
#print(X1.shape)
#print(y.shape)
#
#plt.scatter(X1[:,0],y)
#plt.scatter(X1[:, 1],y)
#plt.title("Pricing Bids")
#plt.xlabel('Price')
#plt.ylabel('Status (1:Won, 0:Lost)')
#plt.show()

#sys.exit(-1)
def perceptron_sgd(X, Y):
    w = np.zeros(len(X[0]))
    eta = 1
    epochs = 20

    for t in range(epochs):
        for i, x in enumerate(X):
            if (np.dot(X[i], w)*Y[i]) <= 0:
                w = w + eta*X[i]*Y[i]

    return w

def perceptron_sgd_plot(X, Y):
    '''
    train perceptron and plot the total loss in each epoch.

    :param X: data samples
    :param Y: data labels
    :return: weight vector as a numpy array
    '''
    w = np.zeros(len(X[0]))
    eta = 1
    n = 30
    errors = []

    for t in range(n):
        total_error = 0
        for i, x in enumerate(X):
            if (np.dot(X[i], w)*Y[i]) <= 0:
                total_error += (np.dot(X[i], w)*Y[i])
                w = w + eta*X[i]*Y[i]
        errors.append(total_error*-1)

    plt.plot(errors)
    plt.xlabel('Epoch')
    plt.ylabel('Total Loss')

    return w

w = perceptron_sgd_plot(X,y)
print(w)

for d, sample in enumerate(X):
    # Plot the negative samples
    if d < 2:
        plt.scatter(sample[0], sample[1], s=120, marker='_', linewidths=2)
    # Plot the positive samples
    else:
        plt.scatter(sample[0], sample[1], s=120, marker='+', linewidths=2)

# Add our test samples

plt.scatter(2,2, s=120, marker='_', linewidths=2, color='yellow')
plt.scatter(4,3, s=120, marker='+', linewidths=2, color='blue')

# Print the hyperplane calculated by perceptron_sgd()
x2=[w[0],w[1],-w[1],w[0]]
x3=[w[0],w[1],w[1],-w[0]]

x2x3 =np.array([x2,x3])
X,Y,U,V = zip(*x2x3)
ax = plt.gca()
ax.quiver(X,Y,U,V,scale=1, color='blue')
plt.show()


import math
import numpy as np
from scipy import signal
from skimage import color as col
from scipy import ndimage as ndi

def G_carrier_real(t, freq, phase):
    '''
    Real part of the carrier.
    '''
    topass = 2 * math.pi * freq * t + phase
    out = np.cos(topass)
    return out

def G_carrier_imag(t, freq, phase):
    '''
    Imaginary part of the carrier.
    '''
    topass = 2 * math.pi * freq * t + phase
    out = np.sin(topass)
    return out

def G_envelope(t, amp, sdev):
    '''
    The impact of the filter is controlled by a Gaussian function.
    '''
    out = amp * np.exp( (-(t/sdev)**2) )
    return out

def G_fil_real(t, paras):
    '''
    Custom-built filter response (real part).
    Assumes that t is an array of temporal inputs.
    '''
    carrier = G_carrier_real(t=t, freq=paras["freq"], phase=paras["phase"])
    envelope = G_envelope(t=t, amp=paras["amp"], sdev=paras["sdev"])
    out = carrier * envelope
    return out

def G_fil_imag(t, paras):
    '''
    Custom-built filter response (imaginary part).
    Assumes that t is an array of temporal inputs.
    '''
    carrier = G_carrier_imag(t=t, freq=paras["freq"], phase=paras["phase"])
    envelope = G_envelope(t=t, amp=paras["amp"], sdev=paras["sdev"])
    out = carrier * envelope
    return out

def my_signal(t):

    highfreq = 0.25 * np.sin((2*math.pi*para_HIGHFREQ*t))
    lowfreq = 2 * np.sin((2*math.pi*para_LOWFREQ*t))

    cond = (np.abs(t) <= 5)
    signal = highfreq + lowfreq
    out = np.select([cond], [signal])

    return out

## Frequency response of the Gabor filter is obtained analytically as the (complex) Fourier transform.
def G_ft_real(f, amp, sdev, freq, phase):
    '''
    Real part of the complex Gabor filter's frequency response.
    '''
    topass = (f - freq) * sdev
    env = G_envelope(t=topass, amp=1, sdev=1)
    out = math.cos(phase) * amp * sdev * env
    return out

def G_ft_imag(f, amp, sdev, freq, phase):
    '''
    Imaginary part of the complex Gabor filter's frequency response.
    '''
    topass = (f - freq) * sdev
    env = G_envelope(t=topass, amp=1, sdev=1)
    out = math.sin(phase) * amp * sdev * env
    return out

def G_fr_real(f, paras):
    '''
    Frequency response for our custom-built filter (real part).
    Assumes that f is an array of frequency settings.
    '''
    out = G_ft_real(f=f, amp=paras["amp"], sdev=paras["sdev"], freq=paras["freq"], phase=paras["phase"])
    return out

def G_fr_imag(f, paras):
    '''
    Frequency response for our custom-built filter (real part).
    Assumes that f is an array of frequency settings.
    '''
    out = G_ft_imag(f=f, amp=paras["amp"], sdev=paras["sdev"], freq=paras["freq"], phase=paras["phase"])
    return out

def G2_carrier_real(x, y, freqx, freqy, phase):
    '''
    Real part of the 2-D Gabor carrier.
    '''
    topass = 2 * math.pi * (freqx*x + freqy*y) + phase
    out = np.cos(topass)
    return out

def G2_carrier_imag(x, y, freqx, freqy, phase):
    '''
    Imaginary part of the 2-D Gabor carrier.
    '''
    topass = 2 * math.pi * (freqx*x + freqy*y) + phase
    out = np.sin(topass)
    return out

def G2_envelope(x, y, amp, sdev):
    '''
    Gaussian envelope for a 2-D Gabor filter.
    We assume that it is circular (same decrease in x/y directions).
    '''
    out = amp * np.exp(-(x**2+y**2)/(sdev**2))
    return out

def G2_fil_real(x, y, paras):
    '''
    Custom-built filter response (real part).
    '''
    # Spatial frequency in polar coordinates.
    u = paras["freqs"] * math.cos(paras["dir"])
    v = paras["freqs"] * math.sin(paras["dir"])
    # Computations.
    carrier = G2_carrier_real(x=x, y=y, freqx=u, freqy=v, phase=paras["phase"])
    envelope = G2_envelope(x=x, y=y, amp=paras["amp"], sdev=paras["sdev"])
    out = carrier * envelope
    return out

def G2_fil_imag(x, y, paras):
    '''
    Custom-built filter response (imaginary part).
    '''
    # Spatial frequency in polar coordinates.
    u = paras["freqs"] * math.cos(paras["dir"])
    v = paras["freqs"] * math.sin(paras["dir"])
    # Computations.
    carrier = G2_carrier_imag(x=x, y=y, freqx=u, freqy=v, phase=paras["phase"])
    envelope = G2_envelope(x=x, y=y, amp=paras["amp"], sdev=paras["sdev"])
    out = carrier * envelope
    return out

def fil_kernel(paras, n_stds=3):
    '''
    Complex values of 2D Gabor filter, for use in convolution.
    When applied to images, this is typically called
    The linear size of the filter is determined as a multiple
    of the standard deviation of the Gaussian envelope, and the
    values passed to the filter are symmetric about zero.

    USAGE: pass the parameters only; the size of the grid of
    response values generated depends on these.
    '''

    pixnum = 2*math.ceil(n_stds*paras["sdev"])

    y0 = pixnum/2
    x0 = pixnum/2
    y, x = np.mgrid[-y0:(y0+1), -x0:(x0+1)]

    # Spatial frequency in polar coordinates.
    u = paras["freqs"] * math.cos(paras["dir"])
    v = paras["freqs"] * math.sin(paras["dir"])
    # Computations.
    envelope = G2_envelope(x=x, y=y,
                           amp=paras["amp"]/(2*math.pi*paras["sdev"]**2),
                           sdev=paras["sdev"])
    out = {"real": None, "imag": None}
    out["real"] = envelope * G2_carrier_real(x=x, y=y, freqx=u, freqy=v, phase=paras["phase"])
    out["imag"] = envelope * G2_carrier_imag(x=x, y=y, freqx=u, freqy=v, phase=paras["phase"])

    return out

def patch_stats(image, grid_w, grid_h):
    '''
    A simple function which takes an image, divides it
    into a (grid_y x grid_x) grid of patches, and iterates
    over the patches, computing per-patch statistics.

    In the special case of grid_x=grid_y=1, stats are for the whole image.
    '''

    pix_h = image.shape[0] # number of pixels
    pix_w = image.shape[1]

    gridsize = grid_w*grid_h

    dh = math.floor(pix_h/grid_h) # typical (non-edge) patch sizes
    dw = math.floor(pix_w/grid_w)

    meanvec = np.zeros(gridsize, dtype=np.float32) # initialize vectors to hold the stats
    medvec = np.zeros(gridsize, dtype=np.float32)
    maxvec = np.zeros(gridsize, dtype=np.float32)
    minvec = np.zeros(gridsize, dtype=np.float32)

    # Loop over the patches, starting at the top-left, and doing one grid row at a time.
    idx = 0
    for i in range(grid_h):

        start_h = i * dh
        if (i+1 == grid_h):
            stop_h = pix_h
        else:
            stop_h = start_h + dh

        for j in range(grid_w):

            start_w = j * dw
            if (j+1 == grid_w):
                stop_w = pix_w
            else:
                stop_w = start_w + dw

            patch = image[start_h:stop_h, start_w:stop_w]
            meanvec[idx] = np.mean(patch) # patch mean
            medvec[idx] = np.median(patch) # patch median
            maxvec[idx] = np.max(patch) # patch maximum
            minvec[idx] = np.min(patch) # patch minimum
            idx += 1

    return {"mean": meanvec, "med": medvec, "max": maxvec, "min": minvec}

def nonlin(u):
    '''
    A non-linear function to pass per-patch magnitude statistics through.
    '''

    return np.log(1+u)

def nonlin(u):
    '''
    A non-linear function to pass per-patch magnitude statistics through.
    '''

    return np.log(1+u)

def G2_getfeatures(ims, fil_paras, gridshape, mode="reflect", cval=0):
    '''
    A routine which takes an array of images with 4 coords.
    Dim 1 and 2: pixel position.
    Dim 3: RGB channel index.
    Dim 4: Time index.
    '''

    num_ims = ims.shape[3]
    num_feats = gridshape[0] * gridshape[1]

    out = np.zeros(num_ims*num_feats, dtype=np.float32).reshape((num_ims,num_feats))

    # Generate the kernel prior to loop over images.
    fil_values = fil_kernel(paras=fil_paras, n_stds=2)

    # Iterate over images.
    for i in range(num_ims):

        featvec = np.arange(0, dtype=np.float32)

        # Slice -> XYZ -> CIE Lab -> Take only Luminance channel.
        im = col.xyz2lab(col.rgb2xyz(ims[:,:,:,i]))[:,:,0]

        # Convolution.
        fil_response_real = ndi.convolve(input=im,
                                         weights=fil_values["real"],
                                         mode=mode, cval=cval)
        fil_response_imag = ndi.convolve(input=im,
                                         weights=fil_values["imag"],
                                         mode=mode, cval=cval)
        fil_response_magnitude = np.sqrt((fil_response_real**2 + fil_response_imag**2))

        # Per-patch statistics.
        imstats = patch_stats(image=fil_response_magnitude, grid_h=gridshape[0], grid_w=gridshape[1])

        # Pass per-patch statistics through non-linearity to compute final feature vector.
        imfeats = nonlin(imstats["mean"])

        # Store the feature vector for this image.
        out[i,:] = imfeats

    # Output is the array of feature vectors, one feature vector for each image.
    return out


import numpy as np
import copy as cp
import math

def get_distance(dictionary, city1, city2):
    """
    Calculate distance between 2 nodes
    :param dictionary: Dictionary. Dict with node names as keys, coordinates as values
    :param city1: int. Name of city
    :param city2: int. Name of city
    :return: float. Distance from one node to another.
    """
    x = dictionary[city1][0] - dictionary[city2][0]
    y = dictionary[city1][1] - dictionary[city2][1]
    return math.sqrt(x ** 2 + y ** 2)

# calculate the total distance
def total_distance(tour, dictionary):
    """
    Calculate total distance of path
    :param tour: list. Current path
    :param dictionary: Dictionary. Dict with node names as keys, coordinates as value
    :return: float. Current length of path
    """
    distance = 0
    for i in range(len(tour) - 1):
        distance += get_distance(dictionary, tour[i], tour[i + 1])

    return distance

def swap(tour):
    """
    Exchange two coordinates and get a candidate solution solution
    :param tour: list. List with current path
    :return: list. List with new path
    """
    c1, c2 = np.random.randint(1, len(tour) - 1, size=2)
    # Swap coordinates, make deepcopy of list
    stour = cp.deepcopy(tour)
    stour[c1], stour[c2] = stour[c2], stour[c1]
    return stour

# inserting
def insert(tour):
    """
    Randomly insert node in random place of path
    :param tour: list. List with current path
    :return: list. List with new path
    """
    randindex = np.random.randint(1, len(tour) - 2)
    randcity = np.random.randint(2, len(tour) - 1)
    instour = cp.deepcopy(tour)
    instour.remove(randcity)
    instour.insert(randindex, randcity)
    return instour

# invert
def invert(tour):
    """
    Invert part of path
    :param tour: list. List with current path
    :return: list. List with new path
    """
    c1, c2 = np.random.randint(1, len(tour) - 1, size=2)
    if c2 < c1:
        a = c2
        b = c1
    else:
        a = c1
        b = c2

    itour = cp.deepcopy(tour)
    itour = itour[:a] + itour[b:a - 1:-1] + itour[b + 1:]
    return itour

def calc_nn(nodes):
    """
    Calculate Euclidean distance to all other nodes in path
    :param nodes:  Dictionary. Dict with node names as keys, coordinates as values
    :return: Dictionary. Dict containing coords and an individual dict for each node,
    containing distances to other neighbor sorted in ascending order.
    """
    for node in range(1, len(nodes) + 1):
        t_dict = dict()
        tour = [i for i in nodes.keys()]
        tour.remove(node)

        for j in tour:
            t_dict[j] = get_distance(nodes, node, j)

        nodes[node].append(sorted(t_dict.items(), key=lambda x: x[1]))

    return nodes


import numpy as np
import math
def hashValue(data, planes):

    signature = 0
    for plane in planes:
        signature = signature << 1
        val = np.dot(plane,data)
        if val >=0:
            signature = signature | 1

    return signature

def onesCount(n):
    count = 0
    if n == 0:
        return 0
    else:
        while n:
            count += 1
            n = n & (n-1)
    return count

def angleCalc(a,b):
    prod = np.dot(a,b)
    magA = sum(a**2) ** 0.5
    magB = sum(b**2) ** 0.5
    cos = prod/magA/magB
    theta = math.acos(cos)

    return theta

dim = 3
bits = 3
run = 1
averageSimilarity = 0

for i in range(run):

    point1 = np.random.randn(dim)
    point2 = np.random.randn(dim)
    print("point1: ",point1)
    print("point2: ",point2)

    #point3 = np.array([1,1,1])

    planes = np.random.randn(bits, dim)

    sig1 = hashValue(point1, planes)
    sig2 = hashValue(point2, planes)
    print("sig1: ", sig1)
    #sig3 = hashValue(point3, planes)

    angle = angleCalc(point1,point2)
    probSameAngle = 1 - (angle/math.pi)

    probSameHash = 1 - (onesCount(sig1^sig2)/bits)

    error = (probSameAngle-probSameHash)/probSameAngle

    print("Angle: ", probSameAngle, "Hash: ", probSameHash, "Error: ", error, "%")


import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
import sys

training_data = []
classes = []

def readData(filenameX,filenameY): # Read data from filenames
	global training_data
	global classes
	training_data = pd.read_fwf(filenameX,header=None,usecols=[0,1])
	classes = pd.read_csv(filenameY,header=None,usecols=[0])

readData(sys.argv[1],sys.argv[2])

examples_count = training_data.shape[0]
dimensions = training_data.shape[1]
training_data = np.array(training_data.values,dtype='f')
training_data = np.reshape(training_data,[examples_count,dimensions])

labels = []

for i in range(examples_count): # Create a label vector
	if classes.values[i] == 'Alaska':
		labels.append(0)
	elif classes.values[i] == 'Canada':
		labels.append(1)

labels = np.reshape(np.array(labels,dtype='f'),[examples_count,1])
labels_comp = (labels+1)%2

covariance = np.zeros([dimensions,dimensions])
phi = sum(labels)/float(examples_count) #Bernoulli variable for y

mean_0 = np.matmul(np.transpose(training_data),labels_comp)/sum(labels_comp) #Mean for class 0
mean_1 = np.matmul(np.transpose(training_data),labels)/sum(labels) # Mean for class 1

for i in range(examples_count):
	add = np.matmul(np.subtract(np.reshape(training_data[i],[2,1]),mean_0*labels_comp[i]+mean_1*labels[i]),np.transpose(np.subtract(np.reshape(training_data[i],[2,1]),mean_0*labels_comp[i]+mean_1*labels[i])))
	covariance = np.add(covariance,add)
covariance = covariance/examples_count # Covariance matrix

intercept = np.matmul(np.transpose(mean_1),np.matmul(np.linalg.inv(covariance),mean_1))
intercept = intercept - np.matmul(np.transpose(mean_0),np.matmul(np.linalg.inv(covariance),mean_0))
intercept = (intercept - 2*np.log(phi/(1-phi))).flatten() # Compute the intercept term in linear equation

linear = (2*np.matmul(np.linalg.inv(covariance),np.subtract(mean_0,mean_1))).flatten()

zeros = {}
ones = {}
zeros["x1"] = []
zeros["x2"] = []
ones["x1"] = []
ones["x2"] = []

for i in range(examples_count): # Separate data into classes
	if labels[i] == 1:
		ones["x1"].append(training_data[i][0])
		ones["x2"].append(training_data[i][1])
	elif labels[i] == 0:
		zeros["x1"].append(training_data[i][0])
		zeros["x2"].append(training_data[i][1])

min1 = min([min(zeros["x1"]),min(ones["x1"])])
max1 = max([max(zeros["x1"]),max(ones["x1"])])

x1 = np.linspace(min1,max1,100)
x2 = -1*(intercept+linear[0]*x1)/linear[1]

plt.scatter(zeros["x1"],zeros["x2"],c='r',marker='o',label='Alaska') # Plot data
plt.scatter(ones["x1"],ones["x2"],c='b',marker='^',label='Canada')
plt.xlabel('Fresh Water Diameter')
plt.ylabel('Marine Water Diameter')
plt.legend(loc='upper right')
plt.title('Data')
plt.show()

if int(sys.argv[3]) == 0:
	print("Mean_0",mean_0)
	print("Mean_1",mean_1)
	print("Covariance",covariance)
	plt.scatter(zeros["x1"],zeros["x2"],c='r',marker='o',label='Alaska')
	plt.scatter(ones["x1"],ones["x2"],c='b',marker='^',label='Canada')
	plt.plot(x1,x2,c='g',label='Linear Boundary') # Plot linear boundary
	plt.xlabel('Fresh Water Diameter')
	plt.ylabel('Marine Water Diameter')
	plt.legend(loc='upper right')
	plt.title('Linear Seperator')
	plt.show()

covariance_0 = np.zeros([dimensions,dimensions]) # Different covariance matrix
covariance_1 = np.zeros([dimensions,dimensions])

for i in range(examples_count):
	add = np.matmul(np.subtract(np.reshape(training_data[i],[2,1]),mean_0*labels_comp[i]+mean_1*labels[i]),np.transpose(np.subtract(np.reshape(training_data[i],[2,1]),mean_0*labels_comp[i]+mean_1*labels[i])))
	covariance_0 = np.add(covariance_0,add*labels_comp[i])
	covariance_1 = np.add(covariance_1,add*labels[i])

covariance_0 = covariance_0/sum(labels_comp)
covariance_1 = covariance_1/sum(labels)

intercept = np.matmul(np.transpose(mean_1),np.matmul(np.linalg.inv(covariance_1),mean_1))
intercept = intercept - np.matmul(np.transpose(mean_0),np.matmul(np.linalg.inv(covariance_0),mean_0))
intercept = (intercept - 2*np.log(phi/(1-phi))).flatten() # Constant term in quadratic equation

linear = np.matmul(np.linalg.inv(covariance_0),mean_0)
linear = (2*np.subtract(linear,np.matmul(np.linalg.inv(covariance_1),mean_1))).flatten() # Linear terms

quadratic = np.subtract(np.linalg.inv(covariance_1),np.linalg.inv(covariance_0)) # Quadratic terms

z1 = np.copy(x1)

def solveforZ2(z1): # Solve for z2 given z1 using the quadratic equation
	c = intercept+quadratic[0][0]*z1*z1+linear[0]*z1
	b = linear[1]+2*quadratic[0][1]*z1
	a = quadratic[1][1]
	return((-b+np.sqrt(b*b-4*a*c))/(2*a))

z2 = solveforZ2(z1)

if int(sys.argv[3]) == 1:
	print("Mean_0",mean_0)
	print("Mean_1",mean_1)
	print("Covariance_0",covariance_0)
	print("Covariance_1",covariance_1)
	plt.scatter(zeros["x1"],zeros["x2"],c='r',marker='o',label='Alaska')
	plt.scatter(ones["x1"],ones["x2"],c='b',marker='^',label='Canada')
	plt.plot(x1,x2,c='g',label='Linear Boundary')
	plt.plot(z1,z2,c='y',label='Quadratic Boundary') # Plot the quadratic boundary
	plt.xlabel('Fresh Water Diameter')
	plt.ylabel('Marine Water Diameter')
	plt.legend(loc='upper right')
	plt.title('Quadratic Seperator')
	plt.show()


import numpy as np

def LoadFile(filename):		#load input file containing training data
	lines = open(filename, "rb")
	dataset =[]
	for line in lines:
		line = line.strip().split(',')
		dataset.append(line)
	dataset = np.array(dataset).astype(np.float64)
	return dataset

def ByClass(dataset):		#separate data by class
	classes = np.unique(dataset[:,-1])
	div_class = {}
	for i in classes:
		div_class[i] = dataset[dataset[:,-1] == i]
	return div_class

def Mean(data):
	mean = data.mean(axis = 0)
	return mean

def Tresh(vector, data1, data2):
	mu1 = Mean(np.dot(vector, data1.T))
	mu2 = Mean(np.dot(vector, data2.T))
	return (mu1+mu2)/2, mu1, mu2

def main(dataset):		#assuming given two class problem
	div_data = ByClass(dataset)
	class1, class2 = div_data
	class1_data, class2_data = div_data[class1], div_data[class2]
	class1_data = class1_data[:,:-1]
	class2_data = class2_data[:,:-1]
	mean1 = Mean(class1_data)
	mean2 = Mean(class2_data)
	mean = Mean(dataset[:,:-1])
	mean1, mean2, mean = mean1.T, mean2.T, mean.T

	m,n = class1_data.shape
	diff1 = class1_data - np.array(list(mean1)*m).reshape(m,n)
	m,n = class2_data.shape
	diff2 = class2_data - np.array(list(mean2)*m).reshape(m,n)
	diff = np.concatenate([diff1, diff2])
	m, n = diff.shape
	withinClass = np.zeros((n,n))
	diff = np.matrix(diff)
	for i in xrange(m):
		withinClass += np.dot(diff[i,:].T, diff[i,:])
	opt_dir_vector = np.dot(np.linalg.inv(withinClass), (mean1 - mean2))
	print 'Vector = ', np.matrix(opt_dir_vector).T

	threshold, mu1, mu2 = Tresh(opt_dir_vector, class1_data, class2_data)
	print 'Threshold = ', threshold, 'm1 = ', mu1, 'm2 = ', mu2

if __name__ == '__main__':
	filename = 'data.txt'
	dataset = LoadFile(filename)
	main(dataset)


#!/usr/bin/env python3

import numpy as np
import operator as op
from functools import reduce

#question 18 triangle sum

#By starting at the top of the triangle below and
#moving to adjacent numbers on the row below, the
#maximum total from top to bottom is 23.
#3
#7 4
#2 4 6
#8 5 9 3

#That is, 3 + 7 + 4 + 9 = 23.
#Find the maximum total from top to bottom of the triangle below:

grid='''75
95 64
17 47 82
18 35 87 10
20 04 82 47 65
19 01 23 75 03 34
88 02 77 73 07 63 67
99 65 04 28 06 16 70 92
41 41 26 56 83 40 80 70 33
41 48 72 33 47 32 37 16 94 29
53 71 44 65 25 43 91 52 97 51 14
70 11 33 28 77 73 17 78 39 68 17 57
91 71 52 38 17 14 91 43 58 50 27 29 48
63 66 04 68 89 53 67 30 73 16 69 87 40 31
04 62 98 27 23 09 70 98 73 93 38 53 60 04 23
'''

# idea. start from end and check at each step the max value
# then check sums of possible routes, keep max
# didn't work :-(

# convert string to matrix
lines = grid.splitlines()

# create matrix to hold data
grid_n = np.zeros(shape=(len(lines),len(lines)))

for i in range(len(lines)):
  num_str = lines[i]
  nums = np.asarray(num_str.split(' '))
  grid_n[i,:len(nums)] = nums

#print(grid_n)

def walk_sum(grid,row,col):
  if row==0: return grid[0,0]
  if (row>0):
    if(col>0):
      temp1=grid[row-1,col]
      temp2=grid[row-1,col-1]
      if temp1>temp2:
        return(grid[row,col]+walk_sum(grid,row-1,col))
      return(grid[row,col]+walk_sum(grid,row-1,col-1))
    return(grid[row,col]+walk_sum(grid,row-1,col))

count = 0
#print(grid_n.shape)
#for i in range(grid_n.shape[1]):
#  temp = walk_sum(grid_n,grid_n.shape[0]-1,i)
#  if temp > count: count = temp

#print(count)

# idea 2 - optimal substructure!
# start from top, and calculate max sum for each element
# at the bottom, take the max

def max_sum(grid):
  grid_sum = np.zeros(shape=(grid.shape[0],grid.shape[1]))

  for row in range(0,grid.shape[0]):
    for col in range(0,row+1):
      #print(row,col, grid[row,col])
      grid_sum[row,col] = grid[row,col]
      if row==0:
        if col==0: grid_sum[0,0] = grid[0,0]
        else: grid_sum[row,col] += grid_sum[row-1,col]
        #print("row 0,", row,grid[row-1,col],grid_sum[row,col])
      elif col==row:
        grid_sum[row,col] += grid_sum[row-1,col-1]
        #print("col=row,", row,grid[row-1,col-1],grid_sum[row,col])
      else:
        grid_sum[row,col] += max([grid_sum[row-1,col-1],grid_sum[row-1,col]])
  return(grid_sum)

#temp = max_sum(grid_n)
#print(temp,temp[-1,:],max(temp[-1,:]))

# 1074 YAY

#question 17
# count the number of letters in the numbers 1 to 1000
# format
# one hundred and thirty one

digits_str = ['one','two','three','four','five','six','seven','eight','nine']
teens_str = ['ten','eleven','twelve','thirteen','fourteen','fifteen','sixteen','seventeen','eighteen','nineteen']
twenty_plus_str = ['twenty','thirty','fourty','fifty','sixty','seventy','eighty','ninety']

digits = [len(x) for x in digits_str]
teens = [len(x) for x in teens_str]
tens =  [len(x) for x in twenty_plus_str]
hundred = 7
hundred_and = 10
# X hundred *(1+(3+ninty nine others))
one_thou = len('onethousand')

total_sum = 0

# digits and teens
total_sum+= sum(digits) + sum(teens)

# tens are in the form twenty, thrity, then
#  twenty-one two...nine, thirty-one two... nine,
# = twenty appears 9 times more
# but the number one appears 8 times more for each twenty,
# so 8*9

total_sum += 9*(sum(tens) + 8*sum(digits))
sumto99 = total_sum

# hundreds are of the form
# one hundred, two, three... nine
# one hundred AND one... ninety nine... nine hundred AND one... ninety nine
# -> hundred appears nine times more digits one time
# -> sumto99 appears 9 times more + hundred_and *90 (less 9 bc not including 100,200,300)

total_sum += 9*(hundred + sum(digits))
total_sum += 9*sumto99 + 90*hundred_and

# one thousand once
total_sum += one_thou

print(total_sum)

#sum_to_99 = sum(digits) + sum(teens) + sum(tens) + sum(tens)*sum(digits)

#total_num_sum = sum_to_99+ sum(hundreds[0]*digits)+sum([x*sum_to_99 for x in hundreds])*sum(digits)

#print([x*sum_to_99 for x in hundreds if x>7])
#print(sum_to_99,total_num_sum)


# In[1]:

import pymc as pm
import numpy as np

# Model
# -----
# Consider the following true generative model:
#
# $$ x_{true} \sim \textrm{Normal}(2,1) $$
# $$ y_{true} \sim \textrm{Normal}(\textrm{exp}(x_{true}),1)$$
# $$ z_{data} \sim \textrm{Normal}(x_{true} + y_{true},0.75)$$
#
# Where $x_{true}$ is a scalar, $y_{true}$ is a vector of length 2, and $z_{data}$ is a $2\times 20$ matrix.
#
# We can simulate this using Numpy:

# In[2]:

ndims = 2
nobs = 20

xtrue = np.random.normal(scale=2., size=1)
ytrue = np.random.normal(loc=np.exp(xtrue), scale=1, size=(ndims, 1))
zdata = np.random.normal(loc=xtrue + ytrue, scale=.75, size=(ndims, nobs))

# `zdata` is observed but `xtrue` and `ytrue` are not. Thus x and y are unknown, and we want to come up with posterior distributions for them.

# Build Model
# -----------
#
# Now we want to do inference assuming the following model:
#
# $$ x \sim \textrm{Normal}(0,1) $$
# $$ y \sim \textrm{Normal}(\textrm{exp}(x),2)$$
# $$ z \sim \textrm{Normal}(x + y,0.75)$$
#
# The aim here is to get posteriors over $x$ and $y$ given the data we have about $z$ (`zdata`).
#
# We create a new `Model` objects, and do operations within its context. The `with` lets PyMC know this model is the current model of interest.
#
# We construct new random variables with the constructor for its prior distribution such as `Normal` while within a model context (inside the `with`). When you make a random variable it is automatically added to the model. The constructor returns a Theano variable.
#
# Using the constructor may specify the name of the random variable, the parameters of a random variable's prior distribution, as well as the shape of the random variable. We can specify that a random variable is observed by specifying the data that was observed.

# In[3]:

with pm.Model() as model:
    x = pm.Normal('x', mu=0., sd=1)
    y = pm.Normal('y', mu=pm.exp(x), sd=2., shape=(ndims, 1)) # here, shape is telling us it's a vector rather than a scalar.
    z = pm.Normal('z', mu=x + y, sd=.75, observed=zdata) # shape is inferred from zdata

# A parenthetical note on the parameters for the normal. Variance is encoded as `tau`, indicating precision, which is simply inverse variance (so $\tau=\sigma^{-2}$ ). This is used because the gamma function is the conjugate prior for precision, and must be inverted to get variance. Encoding in terms of precision saves the inversion step in cases where variance is actually modeled using gamma as a prior.

# Fit Model
# ---------
# We need a starting point for our sampling. The `find_MAP` function finds the maximum a posteriori point (MAP), which is often a good choice for starting point. `find_MAP` uses an optimization algorithm (`scipy.optimize.fmin_l_bfgs_b`, or [BFGS](http://en.wikipedia.org/wiki/BFGS_method), by default) to find the local maximum of the log posterior.
#
# Note that this `with` construction is used again. Functions like `find_MAP` and `HamiltonianMC` need to have a model in their context. `with` activates the context of a particular model within its block.

# In[4]:

with model:
    start = pm.find_MAP()

# Points in parameter space are represented by dictionaries with parameter names as they keys and the value of the parameters as the values.

# In[5]:

print("MAP found:")
print("x:", start['x'])
print("y:", start['y'])

print("Compare with true values:")
print("ytrue", ytrue)
print("xtrue", xtrue)

# Out[5]:

#     MAP found:
#     x: 2.08679716543
#     y: [[ 7.93662462]
#      [ 9.10291792]]
#     Compare with true values:
#     ytrue [[ 8.09247902]
#      [ 9.01023203]]
#     xtrue [ 2.03525495]
#

# We will use NUTS to sample from the posterior as implemented by the `NUTS` step method class.

# In[6]:

with model:
    step = pm.NUTS()

# The `sample` function takes a number of steps to sample, a step method, a starting point. It returns a trace object which contains our samples.

# In[7]:

with model:
    trace = pm.sample(3000, step, start)

# Out[7]:

# To use more than one sampler, pass a list of step methods to `sample`.
#
# The trace object can be indexed by the variables in the model, returning an array with the first index being the sample index
# and the other indexes the shape of the parameter. Thus for this example:

# In[8]:

trace[y].shape

# Out[8]:

#     (3000, 2, 1)

# `traceplot` is a summary plotting function for a trace.

# In[9]:

pm.traceplot(trace);

# Out[9]:

# image file:

# ## PyMC Internals
#
# ### Model
#
# The `Model` class has very simple internals: just a list of unobserved variables (`Model.vars`) and a list of factors which go into computing the posterior density (`Model.factors`) (see model.py for more).
#
# A Python "`with model:`" block has `model` as the current model. Many functions, like `find_MAP` and `sample`, must be in such a block to work correctly by default. They look in the current context for a model to use. You may also explicitly specify the model for them to use. This allows us to treat the current model as an implicit parameter to these functions.
#
# ### Distribution Classes
#
# `Normal` and other distributions are actually `Distribution` subclasses. The constructors have different behavior depending on whether they are called with a name argument or not (string argument in 1st slot). This allows PyMC to have intuitive model specification syntax and still distinguish between random variables and distributions.
#
# When a `Distribution` constructor is called:
#
# * Without a name argument, it simply constructs a distribution object and returns it. It won't construct a random variable. This object has properties like `logp` (density function) and `expectation`.
# * With a name argument, it constructs a random variable using the distrubtion object as the prior distribution and inserts this random variable into the current model. Then the constructor returns the random variable.
#

# In[10]:

help(model)

# Out[10]:

#     Help on Model in module pymc.model object:
#
#     class Model(Context)
#      |  Base class for encapsulation of the variables and
#      |  likelihood factors of a model.
#      |
#      |  Method resolution order:
#      |      Model
#      |      Context
#      |      __builtin__.object
#      |
#      |  Methods defined here:
#      |
#      |  AddNamed(model, var)
#      |
#      |  Data(model, data, dist)
#      |
#      |  TransformedVar(model, name, dist, trans)
#      |
#      |  Var(model, name, dist)
#      |
#      |  __getitem__(self, key)
#      |
#      |  __init__(self)
#      |
#      |  d2logpc(model, vars=None)
#      |      Compiled log probability density hessian function
#      |
#      |  dlogpc(model, vars=None)
#      |      Compiled log probability density gradient function
#      |
#      |  ----------------------------------------------------------------------
#      |  Data descriptors defined here:
#      |
#      |  cont_vars
#      |      All the continuous variables in the model
#      |
#      |  logp
#      |      log-probability of the model
#      |
#      |      Parameters
#      |      ----------
#      |
#      |      model : Model
#      |
#      |      Returns
#      |      -------
#      |
#      |      logp : Theano scalar
#      |
#      |  logpc
#      |      Compiled log probability density function
#      |
#      |  test_point
#      |      Test point used to check that the model doesn't generate errors
#      |
#      |  ----------------------------------------------------------------------
#      |  Data and other attributes defined here:
#      |
#      |  contexts = []
#      |
#      |  ----------------------------------------------------------------------
#      |  Methods inherited from Context:
#      |
#      |  __enter__(self)
#      |
#      |  __exit__(self, typ, value, traceback)
#      |
#      |  ----------------------------------------------------------------------
#      |  Class methods inherited from Context:
#      |
#      |  get_context(cls) from __builtin__.type
#      |
#      |  get_contexts(cls) from __builtin__.type
#      |
#      |  ----------------------------------------------------------------------
#      |  Data descriptors inherited from Context:
#      |
#      |  __dict__
#      |      dictionary for instance variables (if defined)
#      |
#      |  __weakref__
#      |      list of weak references to the object (if defined)
#
#

# In[10]:


import numpy as np

def ModifyMatrix(A):
    newA = A
    if(A.shape[1]%2 == 1):
        aux = np.zeros((A.shape[0],A.shape[1]+1))
        aux = np.insert(A,A.shape[1],0,axis=1)
        newA = aux
    if(newA.shape[0]%2 == 1):
        aux = np.zeros((newA.shape[0]+1,newA.shape[1]))
        aux = np.insert(newA,newA.shape[0],0,axis=0)
        newA = aux
    return newA

def FastMultiply(oldA,oldB):
    rows = oldA.shape[0]
    columns = oldB.shape[1]
    if(rows <= 2 or columns <=2 or oldA.shape[1] <= 2 or oldB.shape[0] <= 2):
        return np.dot(oldA,oldB)

    A = ModifyMatrix(oldA)
    B = ModifyMatrix(oldB)
    N1 = A.shape[0]
    N2 = A.shape[1]
    N3 = B.shape[0]
    N4 = B.shape[1]

    a = A[0:N1//2,0:N2//2]
    b = A[0:N1//2,N2//2:N2//2+N2//2]
    c = A[N1//2:N1//2+N1//2,0:N2//2]
    d = A[N1//2:N1//2+N1//2,N2//2:N2//2+N2//2]

    e = B[0:N3//2,0:N4//2]
    f = B[0:N3//2,N4//2:N4//2+N4//2]
    g = B[N3//2:N3//2+N3//2,0:N4//2]
    h = B[N3//2:N3//2+N3//2,N4//2:N4//2+N4//2]

    p1 = FastMultiply(a,(f-h))
    p3 = FastMultiply((c+d),e)
    p2 = FastMultiply((a+b),h)
    p4 = FastMultiply(d,(g-e))
    p5 = FastMultiply((a+d),(e+h))
    p6 = FastMultiply((b-d),(g+h))
    p7 = FastMultiply((a-c),(e+f))

    C = np.zeros((rows,columns))

    c11 = p5 + p4 - p2 + p6
    c12 = p1 + p2
    c21 = p3 + p4
    c22 = p1 + p5 - p3 - p7

    for i in range(0,N1//2):
        for j in range(0,N4//2):
            C[i][j] = c11[i][j]
            if(j + N4//2 < columns):
                C[i][j+N4//2] = c12[i][j]
            if(i + N1//2 < rows):
                C[i+N1//2][j] = c21[i][j]
                if(j + N4//2 < columns):
                    C[i+N1//2][j+N4//2] = c22[i][j]
    return C

MC601-Metodología de la Investigación/strassen.py


# Starting with the number 1 and moving to the right in a clockwise direction a 5 by 5 spiral is formed as follows:

# 21 22 23 24 25
# 20  7  8  9 10
# 19  6  1  2 11
# 18  5  4  3 12
# 17 16 15 14 13

# It can be verified that the sum of the numbers on the diagonals is 101.

# What is the sum of the numbers on the diagonals in a 1001 by 1001 spiral formed in the same way?

import numpy as np
np.set_printoptions(linewidth=240)

size = 1001
z = np.empty((size, size), dtype=np.int64)

count = 1
row = size//2
col = size//2
loc = 0
z[row, col] = 1
while True:
	loc += 1
	for i in range(loc):
		count += 1
		if col+i+1 == size:break
		z[row, col+i+1] = count
	col += loc
	if col == size:
		break
	for i in range(loc):
		count += 1
		z[row+i+1, col] = count
	row += loc

	loc += 1
	for i in range(loc):
		count += 1
		z[row, col-i-1] = count
	col -= loc
	for i in range(loc):
		count += 1
		z[row-i-1, col] = count
	row -= loc
print(np.sum(np.diagonal(z)) + np.sum(np.diagonal(np.rot90(z))) - 1)


import torch
import torch.nn as nn
import numpy as np
import scipy.io as scio
import os
import matplotlib.pyplot as plt

os.environ['CUDA_VISIBLE_DEVICES'] = '0'
torch.manual_seed(1)
np.random.seed(1)

lapl_op = [[[[    0,   0, -1/12,   0,     0],
             [    0,   0,   4/3,   0,     0],
             [-1/12, 4/3,    -5, 4/3, -1/12],
             [    0,   0,   4/3,   0,     0],
             [    0,   0, -1/12,   0,     0]]]]

# ============ define relevant functions =============
# https://github.com/benmaier/reaction-diffusion/blob/master/gray_scott.ipynb

def apply_laplacian(mat, dx = 0.01):
    # dx is inversely proportional to N
    """This function applies a discretized Laplacian
    in periodic boundary conditions to a matrix
    For more information see
    https://en.wikipedia.org/wiki/Discrete_Laplace_operator#Implementation_via_operator_discretization
    """

    # the cell appears 4 times in the formula to compute
    # the total difference
    neigh_mat = -5*mat.copy()

    # Each direct neighbor on the lattice is counted in
    # the discrete difference formula
    neighbors = [
                    ( 4/3,  (-1, 0) ),
                    ( 4/3,  ( 0,-1) ),
                    ( 4/3,  ( 0, 1) ),
                    ( 4/3,  ( 1, 0) ),
                    (-1/12,  (-2, 0)),
                    (-1/12,  (0, -2)),
                    (-1/12,  (0, 2)),
                    (-1/12,  (2, 0)),
                ]

    # shift matrix according to demanded neighbors
    # and add to this cell with corresponding weight
    for weight, neigh in neighbors:
        neigh_mat += weight * np.roll(mat, neigh, (0,1))

    return neigh_mat/dx**2

# Define the update formula for chemicals A and B
def update(A, B, DA, DB, f, k, delta_t):
    """Apply the Gray-Scott update formula"""

    # compute the diffusion part of the update
    diff_A = DA * apply_laplacian(A)
    diff_B = DB * apply_laplacian(B)

    # Apply chemical reaction
    reaction = A*B**2
    diff_A -= reaction
    diff_B += reaction

    # Apply birth/death
    diff_A += f * (1-A)
    diff_B -= (k+f) * B

    A += diff_A * delta_t
    B += diff_B * delta_t

    return A, B

def GetEachTerm(A, B, DA, DB, f, k, delta_t, dx):
    lap_A = DA * apply_laplacian(A,dx)
    lap_B = DB * apply_laplacian(B,dx)
    # Apply chemical reaction
    reaction = A * B ** 2

    # Apply birth/death, linear term
    lin_A = f * (1 - A)
    lin_B = (k + f) * B
    return lap_A, lap_B, reaction, lin_A, lin_B

def update_rk4(A0, B0, DA, DB, f, k, delta_t, dx):
    """Update with Runge-kutta-4 method
       See https://en.wikipedia.org/wiki/Runge%E2%80%93Kutta_methods
    """
    ############# Stage 1 ##############
    # compute the diffusion part of the update
    diff_A = DA * apply_laplacian(A0, dx)
    diff_B = DB * apply_laplacian(B0, dx)

    # Apply chemical reaction
    reaction = A0 * B0 ** 2
    diff_A -= reaction
    diff_B += reaction

    # Apply birth/death
    diff_A += f * (1 - A0)
    diff_B -= (k + f) * B0

    K1_a = diff_A
    K1_b = diff_B

    ############# Stage 1 ##############
    A1 = A0 +  K1_a * delta_t/2.0
    B1 = B0 +  K1_b * delta_t/2.0

    diff_A = DA * apply_laplacian(A1, dx)
    diff_B = DB * apply_laplacian(B1, dx)

    # Apply chemical reaction
    reaction = A1 * B1 ** 2
    diff_A -= reaction
    diff_B += reaction

    # Apply birth/death
    diff_A += f * (1 - A1)
    diff_B -= (k + f) * B1

    K2_a = diff_A
    K2_b = diff_B

    ############# Stage 2 ##############

    A2 = A0 + K2_a * delta_t/2.0
    B2 = B0 + K2_b * delta_t/2.0

    diff_A = DA * apply_laplacian(A2, dx)
    diff_B = DB * apply_laplacian(B2, dx)

    # Apply chemical reaction
    reaction = A2 * B2 ** 2
    diff_A -= reaction
    diff_B += reaction

    # Apply birth/death
    diff_A += f * (1 - A2)
    diff_B -= (k + f) * B2

    K3_a = diff_A
    K3_b = diff_B

    ############# Stage 3 ##############
    A3 = A0 + K3_a * delta_t
    B3 = B0 + K3_b * delta_t

    diff_A = DA * apply_laplacian(A3, dx)
    diff_B = DB * apply_laplacian(B3, dx)

    # Apply chemical reaction
    reaction = A3 * B3 ** 2
    diff_A -= reaction
    diff_B += reaction

    # Apply birth/death
    diff_A += f * (1 - A3)
    diff_B -= (k + f) * B3

    K4_a = diff_A
    K4_b = diff_B

    # Final solution
    A = A0 + delta_t*(K1_a+2*K2_a+2*K3_a+K4_a)/6.0
    B = B0 + delta_t*(K1_b+2*K2_b+2*K3_b+K4_b)/6.0

    return A, B

def get_initial_A_and_B(N, random_influence = 0.2):
    """get the initial chemical concentrations"""
    # get initial homogeneous concentrations
    A = (1-random_influence) * np.ones((N,N))
    B = np.zeros((N,N))

    # put some noise on there
    A += random_influence * np.random.random((N,N))
    B += random_influence * np.random.random((N,N))

    # initial disturbance
    N1, N2, N3 = N//4-4, N//2, 3*N//4
    r = int(N/10.0)

    # initial disturbance 1
    A[N1-r:N1+r, N1-r:N1+r] = 0.50
    B[N1-r:N1+r, N1-r:N1+r] = 0.25

#    # initial disturbance 2
#    A[N1-r:N1+r, N3-r:N3+r] = 0.50
#    B[N1-r:N1+r, N3-r:N3+r] = 0.25
#
#    # initial disturbance 3
#    A[N3-r:N3+r, N3-r:N3+r] = 0.50
#    B[N3-r:N3+r, N3-r:N3+r] = 0.25
#
#    # initial disturbance 4
#    A[N3-r:N3+r, N1-r:N1+r] = 0.50
#    B[N3-r:N3+r, N1-r:N1+r] = 0.25

    # initial disturbance 5
    A[N2-r:N2+r, N2-r:N2+r] = 0.50
    B[N2-r:N2+r, N2-r:N2+r] = 0.25
#
#    # initial disturbance 6
#    A[N2-r:N2+r, N3-r:N3+r] = 0.50
#    B[N2-r:N2+r, N3-r:N3+r] = 0.25

    return A, B

def postProcess(output, N, xmin, xmax, ymin, ymax, num, batch, save_path):
    ''' num: Number of time step
    '''
    x = np.linspace(xmin, xmax, N+1)[:-1]
    y = np.linspace(ymin, ymax, N+1)[:-1]
    x_star, y_star = np.meshgrid(x, y)
    u_pred = output[num, 0, :, :]

    # v_star = true[num+25, 1, 1:-1, 1:-1]
    v_pred = output[num, 1, :, :]

    fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(6, 3))
    fig.subplots_adjust(hspace=0.3, wspace=0.3)

    cf = ax[0].scatter(x_star, y_star, c=u_pred, alpha=0.95, edgecolors='none', cmap='hot', marker='s', s=2)
    ax[0].axis('square')
    ax[0].set_xlim([xmin, xmax])
    ax[0].set_ylim([ymin, ymax])
    cf.cmap.set_under('black')
    cf.cmap.set_over('white')
    ax[0].set_title('u-FDM')
    fig.colorbar(cf, ax=ax[0], extend='both')

    cf = ax[1].scatter(x_star, y_star, c=v_pred, alpha=0.95, edgecolors='none', cmap='hot', marker='s', s=2) #
    ax[1].axis('square')
    ax[1].set_xlim([xmin, xmax])
    ax[1].set_ylim([ymin, ymax])
    cf.cmap.set_under('black')
    cf.cmap.set_over('white')
    ax[1].set_title('v-FDM')
    fig.colorbar(cf, ax=ax[1], extend='both')

    # plt.draw()
    plt.savefig(save_path + '/uv_[b=%d][t=%d].png'%(batch, num))
    plt.close('all')

if __name__ == '__main__':
    #################### generate data #####################
    # =========== define model parameters ==========
    # dt should be 1/2 of dx

    # Diffusion coefficients
    DA = 0.16 #2*10**-5
    DB = 0.08 #DA/4

    # define birth/death rates
    f = 0.06 #1/25
    k = 0.062 #3/50

    # grid size
    N = 256 # 128

    # update in time
    delta_t = 1.0 #1.0/2
    # spatial step
    dx = 1.0 #1.0 / N

    # intialize the chemical concentrations, random_incluence=0
    A, B = get_initial_A_and_B(N, random_influence = 0.0)
    A_record = A.copy()[None,...]
    B_record = B.copy()[None,...]

    N_simulation_steps = 15000
    for step in range(N_simulation_steps):
        # Runge-kutta scheme
        #A, B = update(A, B, DA, DB, f, k, delta_t)
        A, B = update_rk4(A, B, DA, DB, f, k, delta_t, dx)

        if step%5 ==0:
            print(step)
            A_record = np.concatenate((A_record, A[None,...]), axis=0)
            B_record = np.concatenate((B_record, B[None,...]), axis=0)

    UV = np.concatenate((A_record[None,...], B_record[None,...]), axis=0)
    save_path = './2DGS_IC1_2x3001x256x256.mat'
    scio.savemat(save_path, {'uv': UV})

    # Plot the result
    output = np.transpose(UV, [1, 0, 2, 3])
    fig_save_path = './2DGS/'
    for i in range(21):
        postProcess(output, N, 0, N*dx, 0, N*dx, num=150*i, batch=1,save_path=fig_save_path)

    plt.figure()
    plt.plot(UV[0, :, 50, 50], alpha=0.6, label='rk4, dt=1.0')
    plt.legend()
    # plt.show()
    plt.savefig(fig_save_path + '/fig[x=50,y=50].png')