import numpy as np
from scipy.interpolate import splev
import matplotlib
matplotlib.rcParams = matplotlib.rc_params_from_file('../../matplotlibrc')
from matplotlib import pyplot as plt

def basis_plot(n, k, res=401):
    """ Plots some b-spline basis functions.
    Uses same knot vector as the circle interpolation problem."""
    # Make the knot vector.
    t = np.array([0]*(k) + range(n) + [n]*(k+1))
    # Preallocate array to store the control points.
    c = np.zeros(t.size - k)
    # Parameter values to use for plot:
    T = np.linspace(0, n, res)
    # Plot each basis function.
    for i in xrange(t.size - k - 1):
        # Set the corresponding coefficient to 1.
        c[i] = 1
        # plot it.
        plt.plot(T, splev(T, (t, c, k)))
        # Set the corresponding coefficient back to 0.
        c[i] = 0.
    # Save and clear the figure.
    plt.savefig("bspline_basis.pdf")
    plt.clf()

if __name__ == "__main__":
    basis_plot(8, 3)


import numpy as np
import pandas as pd
import statsmodels.api as sm
import matplotlib.pyplot as plt
from statsmodels.tsa.seasonal import seasonal_decompose
from statsmodels.tsa.stattools import adfuller

def adfCheck(timeSeries):

    result = adfuller(timeSeries)
    print("Augmented Dicky-Fuller Test")

    labels = ["ADF Test Statistic", "P-value", "# of lags", "Num of Observations Used"]

    for value, label in zip(result, labels):
        print(label + ' : ' + str(value))

    if result[1] <= 0.05:
        print("""
        * Strong Evidence Against Null Hypothesis")
        * Reject Null Hypothesis
        * Data has no unit root, and is therefore stationary""")

    else:
        print("""
        * Weak evidence against null hypothesis
        * Failed to reject null hypothesis
        * Data has a unit root, and it's therefore non-stationary
        """)

# Arima Code Along
dataFrame = pd.read_csv('monthly-milk-production-pounds-p.csv')
dataFrame.columns = ["Month" , "Milk in Pounds per Cow"]

# Dropping the tail of the pandas dataframe
dataFrame.drop(168, axis=0, inplace=True)

dataFrame["Month"] = pd.to_datetime(dataFrame["Month"])
dataFrame.set_index("Month", inplace=True)

timeSeries = dataFrame["Milk in Pounds per Cow"]

# Calculating the Augmented Dickie Fuler
adfCheck(dataFrame["Milk in Pounds per Cow"])

dataFrame["First Difference"] = dataFrame["Milk in Pounds per Cow"] - dataFrame["Milk in Pounds per Cow"].shift(1)
dataFrame["First Difference"].plot()
adfCheck(dataFrame["First Difference"].dropna())
plt.show()

# If the first difference doesn't provide the evidence it's stationary, lets find
# The second difference, if even in the second difference the data is not stationary,
# Then the data is truly non-stationary
dataFrame["Milk Second Difference"] = dataFrame["First Difference"] - dataFrame["First Difference"].shift(1)
adf_Check = (dataFrame["Milk Second Difference"].dropna())

dataFrame["Milk Second Difference"].plot()
plt.show()

dataFrame["Seasonal First Difference"] = dataFrame["First Difference"] - dataFrame["First Difference"].shift(12)
dataFrame["Seasonal First Difference"].plot()

adfCheck(dataFrame["Seasonal First Difference"].dropna())

import numpy,import statsmodels,from statsmodels


#! /usr/bin/env python
import argparse

import numpy as np
from scipy.optimize import lsq_linear

def rmse(pred: np.ndarray, target: np.ndarray) -> float:
    return np.sqrt(np.mean((pred-target)**2))

def lux(logr: np.ndarray, m: float, b: float) -> np.ndarray:
    return 10**(m * logr + b)

parser = argparse.ArgumentParser(description='Fits least-squares model to lux-resistance data')
parser.add_argument('--input', required=True, help='File with recorded data')
parser.add_argument('--output', required=True, help='Parameters path')
parser.add_argument('--robust', action='store_true', help='Robust fit using Huber Regression')

args = parser.parse_args()

if args.robust:
    from sklearn import linear_model

data = np.loadtxt(args.input, dtype=float, delimiter=',')
target = data[:,1]

# Preprocess data
Y = np.log10(target)
inp = np.log10(data[:,0])

print("")
if args.robust:
    print('Using huber regression ...')
    x = inp.reshape(-1,1)
    reg = linear_model.HuberRegressor()
    reg.fit(x, Y)
    m, b = reg.coef_[0], reg.intercept_
    print(f"Number of outliers: {reg.outliers_.sum()}")
    print(f"Number of iterations: {reg.n_iter_}")
else:
    print('Using least squares regression ...')
    ones = np.ones_like(inp)
    x = np.stack([inp, ones], axis = 1)
    res = lsq_linear(x, Y)
    print(res)
    m, b = res.x[0], res.x[1]

pred=lux(inp, m, b)
err = rmse(pred, target)
np.savetxt(args.output, [m, b])

print("\n\n")
print(f"Root Mean Squared Error: {err}")
print(f"Lux Model parameters: {m}, {b}")
print(f"Done!")


# Code made for Sergio Andrés Díaz Ariza
# 05 March 2021
# License MIT
# Transport Phenomena: Python Program-Assignment 1.1

import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
sns.set()

# Fourier Heat Transfer Equation
def Qcond(Kc,T1,T2,As,Dx):
    # Kc = [W/m*K]
    DT = T2-T1
    z = -Kc*As*(DT/Dx) #[W]
    return z #[W]

##########################################
# Heat Loss ranging Temperatures outside #
# and changing thermal conductivities    #
##########################################

Range_temp = np.arange(-15,38,1) #Range of temperatures to evalute

y = Qcond(0.85,25,Range_temp,20,0.30)
y1 = Qcond(0.75,25,Range_temp,20,0.30)
y2 = Qcond(1.25,25,Range_temp,20,0.30)

plt.figure(1)
plt.plot(Range_temp,y,color='r',label="$Kc$ 0.85")
plt.plot(Range_temp,y1,color='b',label="$Kc$ 0.75")
plt.plot(Range_temp,y2,color='g',label="$Kc$ 1.25")
plt.xticks(np.arange(-15,38,5))
plt.title("Heat Rate Conduction\t$vs$\tRanging Temperature Wall Concrete",fontsize= 18)
plt.xlabel("Temperature\t[$K$]",fontsize= 14)
plt.ylabel("$\dot{Q}_{conduction}$\t$[W]$",fontsize= 14)
plt.legend()

##########################################
# Heat Loss ranging Temperatures outside #
# and changing Thickness wall            #
##########################################

Range_thick = np.linspace(0.10,0.50,num=53) #Range of thickness to evalute

y = Qcond(0.85,25,Range_temp,20,Range_thick)
y1 = Qcond(0.75,25,Range_temp,20,Range_thick)
y2 = Qcond(1.25,25,Range_temp,20,Range_thick)

fig = plt.figure(2)
ax1 = fig.add_subplot(111)
ax2 = ax1.twiny()

ax1.plot(Range_thick,y,color='r',label="$Kc$ 0.85")
ax1.plot(Range_thick,y1,color='b',label="$Kc$ 0.75")
ax1.plot(Range_thick,y2,color='g',label="$Kc$ 1.25")
ax1.set_xlim(0.10,0.50)
ax2.set_xlim(-15,38)
ax2.set_xticks(np.linspace(-15, 38, num=9))
ax2.set_xlabel("Temperature\t$[K]$",fontsize= 14)
ax1.set_xlabel("Thickness Wall\t$[m]$",fontsize= 14)
ax1.set_ylabel("$\.{Q}_{conduction}$\t${W}$",fontsize= 14)
plt.title("Heat Rate Conduction $vs$ Ranging Thickness $&$ Temperatures in Wall Concrete",fontsize= 18)
ax1.legend()
plt.show()


import matplotlib.pyplot as plt
import numpy as np

u = np.linspace(-1, 1, 200)
v = np.linspace(-np.pi, 3, 360)
uu, vv = np.meshgrid(u, v)
z0 = uu + 1j * vv
z = np.exp(z0)
T = np.arctan2(uu, vv)

plt.figure(figsize=(14, 6))
plt.subplot(1, 2, 1)
plt.scatter(uu, vv, c=T, s=10, lw=0, cmap='hsv')
plt.title('real points')
plt.xlabel('Re(z)')
plt.ylabel('Im(z)')
plt.xlim(-3, 3)
plt.ylim(-4, 4)
plt.grid(True)

plt.subplot(1, 2, 2)
plt.scatter(np.real(z), np.imag(z), c=T, s=10, lw=0, cmap='hsv')
plt.title('f(z)=exp(z)')
plt.xlabel('Re(z)')
plt.ylabel('Im(z)')
plt.xlim(-3, 3)
plt.ylim(-3, 3)
plt.grid(True)
plt.show()


#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import numpy as np
from scipy.interpolate import splprep, splev, BSpline

def measure_spline(xyzs, offset = 0):
    ''' Calculate curvature, torsion of a curve, and axial vector under TNB
        frame, also known as Frenet-Serret frame.
        DOI: 10.1007/s00894-013-1819-7
        URL: https://janakiev.com/blog/framing-parametric-curves/

        Suppose a helix is parameterized by a function h(t), in which t
        traverses a set of integers.  So dt = 1.  Thus, np.gradient is a
        right way to obtain derivatives like dx/dt, dy/dt, and dz/dt.
        In fact, as long as it is evenly spaced by m, the gradient should
        return the right value that is scaled by m.
        (x..., y..., z...)
    '''
    # Obtain derivatives...
    dr1 = np.gradient(xyzs, axis = 1)
    dr2 = np.gradient(dr1,  axis = 1)
    dr3 = np.gradient(dr2,  axis = 1)

    # Obtain T vector...
    norm_dr1 = np.linalg.norm(dr1, axis = 0, keepdims = True)
    tvec = dr1 / norm_dr1

    # Obtain B vector...
    bvec_aux = np.cross(dr1.T, dr2.T).T
    norm_bvec_aux = np.linalg.norm(bvec_aux, axis = 0, keepdims = True)
    bvec = bvec_aux / norm_bvec_aux

    # Obtain N vector...
    nvec_aux = np.cross(bvec.T, tvec.T).T
    norm_nvec_aux = np.linalg.norm(nvec_aux, axis = 0, keepdims = True)
    nvec = nvec_aux / norm_nvec_aux

    # Obtain axial vector...
    # Get norm of db and dt
    db = bvec[:, 1:] - bvec[:, :-1]
    dt = tvec[:, 1:] - tvec[:, :-1]
    norm_db = np.linalg.norm(db, axis = 0, keepdims = True)
    norm_dt = np.linalg.norm(dt, axis = 0, keepdims = True)

    # Get axial vector...
    # Refer to 10.1007/s00894-013-1819-7
    db_div_dt = norm_db / norm_dt
    rt = (1 + db_div_dt)**(-2)
    rb = db_div_dt * rt
    avec  = rt * bvec[:, :-1] + rb * tvec[:, :-1]
    norm_avec = np.linalg.norm(avec, axis = 0, keepdims = True)

    # Obtain curvature...
    curv = norm_bvec_aux / norm_dr1 ** 3

    # Obtain torsion...
    tor_aux = np.nansum(bvec_aux * dr3, axis = 0, keepdims = True)
    tor  = tor_aux / (norm_bvec_aux**2)

    # Obtain angular turn per atom...
    nvec_dot = np.nansum( nvec[:, :-1] * nvec[:,1:], axis = 0 )
    nvec_cosang = np.zeros(len(nvec_dot) + 1)
    nvec_cosang[:-1] = np.arccos(nvec_dot)
    nvec_cosang[-1]  = np.nan

    # Calculate radius and pitch...
    # Refer to 10.1007/s00214-009-0639-4
    denorm = curv ** 2 + tor ** 2
    radius = curv / denorm
    ## rise_per_res  = tor / denorm

    # Calculate rise per residue...
    dxyz = np.array(xyzs)[:, 1:] - np.array(xyzs)[:, :-1]
    norm_dxyz = np.linalg.norm(dxyz, axis = 0, keepdims = True)
    rise_dot = np.nansum( dxyz * avec, axis = 0 )
    rise_cosang = rise_dot / (norm_dxyz * norm_avec)
    rise_per_res = norm_dxyz * rise_cosang

    sli = slice(offset, len(xyzs[0])-offset, 1)
    return tvec        [:, sli], \
           nvec        [:, sli], \
           bvec        [:, sli], \
           avec        [:, sli], \
           curv        [:, sli], \
           tor         [:, sli], \
           nvec_cosang [sli], \
           radius      [:, sli], \
           rise_per_res[:, sli]

def fit_spline(xyzs, s = 0, k = 3, num = 100):
    ''' Fit a spline curve along coordinates saved in xyzs.

        xyzs has a dimension of (3, ...).  Transpose xyzs if the dimension is
        (..., 3)
    '''
    tck, u = splprep(xyzs, s = s, k = 3)

    # By default, u.min() => 0, u.max() => 1
    u_fine = np.linspace(u.min(), u.max(), num)
    x, y, z = splev(u_fine, tck)

    return x, y, z


import numpy as np

# transfer function
def transfer(matrix):
    res = np.array(matrix)
    for x in np.nditer(res, op_flags=['readwrite']):
        if x[...] > 0.5:
            x[...] = 1
        else:
            x[...] = 0
    return res

# sigmoid function
def sigmoid(x, derivative=False):
    if derivative:
        return x * (1 - x)
    return 1 / (1 + np.exp(-x))

# input training
X = np.array([[0, 0, 1],
              [0, 1, 1],
              [1, 0, 1],
              [1, 1, 1]])

# output samples
Y = np.array([[0, 0, 1, 1]]).T

# seed random numbers to make calculation deterministic (Deterministic algorithm)
np.random.seed(1)

# initialize weights randomly [-1..1]
syn0 = 2 * np.random.random((3, 1)) - 1

# training
for i in range(10000):
    l0 = X
    l1 = sigmoid(l0.dot(syn0))
    l1_error = Y - l1
    l1_delta = l1_error * sigmoid(l1, True)
    syn0 += l0.T.dot(l1_delta)

print("Weights After Training:")
print(syn0)

print("\n")
print("TESTING")
print(""
      "- Out1: without transfer function\n"
      "- Out2: with transfer function\n"
      "")
print('{0:10} {1:15} {2:10}'.format("Input", "Out1", "Out2"))
# input testing
TX = np.array([[0, 0, 0],
               [0, 0, 1],
               [0, 1, 0],
               [0, 1, 1],
               [1, 0, 0],
               [1, 0, 1],
               [1, 1, 0],
               [1, 1, 1]])

Res = sigmoid(TX.dot(syn0))
Res2 = transfer(Res)
for index in range(len(TX)):
    print('{0:10} {1:15} {2:10}'.format(TX[index], Res[index], Res2[index]))


"""
CSCC11 - Introduction to Machine Learning, Winter 2020, Assignment 1
B. Chan, S. Wei, D. Fleet

===========================================================

 COMPLETE THIS TEXT BOX:

 Student Name: Abhishek Chatterjee
 Student number: 1004820615
 UtorID: chatt114

 I hereby certify that the work contained here is my own

  Abhishek Chatterjee
 (sign with your name)

===========================================================
"""

import numpy as np

class PolynomialRegression:
    def __init__(self, K):
        """ This class represents a polynomial regression model.

        TODO: You will need to implement the methods of this class:
        - predict(X): ndarray -> ndarray
        - fit(train_X, train_Y): ndarray, ndarray -> None
        - fit_with_l2_regularization(train_X, train_Y, l2_coef): ndarray, ndarray, float -> None
        Implementation description will be provided under each method.

        NOTE: The bias term is the first element in self.parameters (i.e. self.parameters = [w_0, w_1, ..., w_K]^T).

        Args:
        - K (int): The degree of the polynomial. Note: 1 <= K <= 10

        ASIDE: Can you see how we can abstract this code?
        """
        assert 1 <= K <= 10, f"K must be between 1 and 10. Got: {K}"
        self.K = K

        # Remember that we have K weights and 1 bias.
        self.parameters = np.ones((K + 1, 1), dtype=np.float)

    def predict(self, X):
        """ This method predicts the output of the given input data using the model parameters.
        Recall that a polynomial function is defined as:

        Given a single scalar input x,
        f(x) = w_0 + w_1 * x + w_2 * x^2 + ... + w_K * x^K

        TODO: You will need to implement the above function and handle multiple scalar inputs,
              formatted as a N-column vector.

        NOTE: You must not iterate through inputs.

        Args:
        - X (ndarray (shape: (N, 1))): A N-column vector consisting N scalar input data.

        Output:
        - ndarray (shape: (N, 1)): A N-column vector consisting N scalar output data.
        """
        assert X.shape == (X.shape[0], 1)

        # ====================================================
        # TODO: Implement your solution within the box

        # need to create a Vandermonde matrix in order to multiply arrays together to create final polynomial

        B = np.vander(X.flatten(), self.K+1, True)
        y = np.matmul(B, self.parameters)

        return y

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

    def fit(self, train_X, train_Y):
        """ This method fits the model parameters, given the training inputs and outputs.

        Recall that the optimal parameters are:
        parameters = (X^{T}X)^{-1}X^{T}Y

        TODO: You will need to replace self.parameters to the optimal parameters. Remember that the shape
              of the self.parameters is (K + 1, 1), where the first entry is the bias

        NOTE: Do not forget that we are using polynomial basis functions!

        Args:
        - train_X (ndarray (shape: (N, 1))): A N-column vector consisting N scalar training inputs.
        - train_Y (ndarray (shape: (N, 1))): A N-column vector consisting N scalar training outputs.
        """
        assert train_X.shape == train_Y.shape and train_X.shape == (train_X.shape[0], 1), f"input and/or output has incorrect shape (train_X: {train_X.shape}, train_Y: {train_Y.shape})."
        assert train_X.shape[0] >= self.K, f"require more data points to fit a polynomial (train_X: {train_X.shape}, K: {self.K}). Do you know why?"

        # ====================================================
        # TODO: Implement your solution within the box

        B = np.vander(train_X.flatten(), self.K+1, True)
        p1 = np.linalg.inv(np.matmul(B.T, B))
        p2 = np.matmul(B.T, train_Y)

        self.parameters = np.matmul(p1, p2)
        # ====================================================

        assert self.parameters.shape == (self.K + 1, 1)

    def fit_with_l2_regularization(self, train_X, train_Y, l2_coef):
        """ This method fits the model parameters with L2 regularization, given the training inputs and outputs.

        Recall that the optimal parameters are:
        parameters = (X^{T}X + lambda*I)^{-1}X^{T}Y

        TODO: You will need to replace self.parameters to the optimal parameters. Remember that the shape
              of the self.parameters is (K + 1, 1), where the first entry is the bias

        NOTE: Do not forget that we are using polynomial basis functions!

        Args:
        - train_X (ndarray (shape: (N, 1))): A N-column vector consisting N scalar training inputs.
        - train_Y (ndarray (shape: (N, 1))): A N-column vector consisting N scalar training outputs.
        - l2_coef (float): The lambda term that decides how much regularization we want.
        """
        assert train_X.shape == train_Y.shape and train_X.shape == (train_X.shape[0], 1), f"input and/or output has incorrect shape (train_X: {train_X.shape}, train_Y: {train_Y.shape})."

        # ====================================================
        # TODO: Implement your solution within the box

        B = np.vander(train_X.flatten(), self.K+1, True)
        p1 = np.matmul(B.T, B)
        p2 = np.linalg.inv(p1 + l2_coef * np.identity(self.K+1))
        p3 = np.matmul(B.T, train_Y)

        self.parameters = np.matmul(p2, p3)

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

        assert self.parameters.shape == (self.K + 1, 1)

    def compute_mse(self, X, observed_Y):
        """ This method computes the mean squared error.

        Args:
        - X (ndarray (shape: (N, 1))): A N-column vector consisting N scalar inputs.
        - observed_Y (ndarray (shape: (N, 1))): A N-column vector consisting N scalar observed outputs.

        Output:
        - (float): The mean squared error between the predicted Y and the observed Y.
        """
        assert X.shape == observed_Y.shape and X.shape == (X.shape[0], 1), f"input and/or output has incorrect shape (X: {X.shape}, observed_Y: {observed_Y.shape})."
        pred_Y = self.predict(X)
        return ((pred_Y - observed_Y) ** 2).mean()

if __name__ == "__main__":
    # You can use linear regression to check whether your implementation is correct.
    # NOTE: This is just a quick check but does not cover all cases.
    model = PolynomialRegression(K=1)
    train_X = np.expand_dims(np.arange(10), axis=1)
    train_Y = np.expand_dims(np.arange(10), axis=1)

    model.fit(train_X, train_Y)
    optimal_parameters = np.array([[0.], [1.]])
    print("Correct optimal weights: {}".format(np.allclose(model.parameters, optimal_parameters)))

    pred_Y = model.predict(train_X)
    print("Correct predictions: {}".format(np.allclose(pred_Y, train_Y)))

    # Change parameters to suboptimal for next test
    model.parameters += 1
    model.fit_with_l2_regularization(train_X, train_Y, l2_coef=0)
    print("Correct optimal weights: {}".format(np.allclose(model.parameters, optimal_parameters)))

    # Regularization pulls the weights closer to 0.
    optimal_parameters = np.array([[0.0231303], [0.99460293]])
    model.fit_with_l2_regularization(train_X, train_Y, l2_coef=0.5)
    print("Correct optimal weights: {}".format(np.allclose(model.parameters, optimal_parameters)))


import numpy as np

def magnitude(x, y, z):
    """
    Magnitude signal computed from the previous three signals.
    This magnitude is computed as the square root of the sum
    of squared components (accelerometer signals).
    :param ax:
    :param ay:
    :param az:
    :return:
    """
    x2 = np.square(x)
    y2 = np.square(y)
    z2 = np.square(z)
    sum = np.sum([x2, y2, z2], axis=0)
    return np.sqrt(sum)

def jerk(acc, time):
    result = np.zeros(len(acc))
    for i, value in enumerate(acc[1:]):
        da = value - acc[i]
        dt = time[i+1] - time[i]
        result[i + 1] = da / dt
    return result

def fft(array):
    """
    Fast Fourier transforms (FFTs)
    :param array:
    :return:
    """
    return np.fft.fft(array)

def sma(x, y=None, z=None):
    if y is None and z is None:
        return np.mean(np.abs(x))
    else:
        return np.mean(np.abs(x) + np.abs(y) + np.abs(z))


from scipy.ndimage import imread
from scipy import signal
import numpy as np
from scipy.ndimage.filters import gaussian_filter
from scipy.ndimage.filters import convolve as filter2
import matplotlib.pyplot as plt
# import cv2

print("This code executes Horn - Schunck algorithm")

"""
the assumption is that groups of pixels move similarly, but not the same.
"""
"""
https://stackoverflow.com/questions/39382412/crop-center-portion-of-a-numpy-image
"""
def crop_center(img,cropx,cropy):
    y,x = img.shape
    startx = x//2-(cropx//2)
    starty = y//2-(cropy//2)
    return img[starty:starty+cropy,startx:startx+cropx]

# im1_ = imread("./img/synth_img_1.png",flatten=True).astype(float)
# im2_ = imread("./img/synth_img_2.png",flatten=True).astype(float)
im1_ = imread("./img/Urban/frame07.png",flatten=True).astype(float)
im2_ = imread("./img/Urban/frame08.png",flatten=True).astype(float)
# im1_ = imread("./img/darcy_3.png",flatten=True).astype(float)
# im2_ = imread("./img/darcy_4.png",flatten=True).astype(float)

ly, lx = im1_.shape
print("lx", lx, "ly", ly)
# im1_= crop_center(im1_,430,400)
# im2_= crop_center(im2_,430,400)

# crop_face = im1_[181:377,450:717]
# print("size", im1_.shape)
# plt.imshow(crop_face)
# plt.show()
"""
Gaussian filter for non synthetic images
"""
sigma = 2
order = 0
im1_ = gaussian_filter(im1_,sigma, order) #
im2_ = gaussian_filter(im2_,sigma, order) #

"""
Gradient (first-order derivatives)
"""
dx_kernel = (1./4)*np.array([[-1, 1],[-1, 1]])
dy_kernel = (1./4)*np.array([[-1, -1],[1, 1]])
dt_kernel = (1./4)*np.ones([2,2])

# fx = signal.convolve2d(im1_, dx_kernel, boundary='symm','same') + signal.convolve2d(im2_, dx_kernel, boundary='symm','same')
fx = filter2(im1_,dx_kernel) + filter2(im2_,dx_kernel)
fy = filter2(im1_,dy_kernel) + filter2(im2_,dy_kernel)
ft = filter2(im1_,dt_kernel) + filter2(im2_,-dt_kernel)
"""
Algorithm

Alpha affects the weight of the gradient in the calculation of the motion vector.
The bigger lambda is, the smaller the effect of the gradient in the u and v vectors, and the larger the effect of the Laplacian
Greater lambda produces greater directional accuracy in the vectors
Greater lambda produces shorter direction vectors, distorting the displacement magnitudes slightly.
The number of iterations affects the sensitivity and accuracy of the detection.
"""
# print "Image t_0 size: ",im1_.shape
u = np.zeros([im1_.shape[0],im1_.shape[1]])
v = np.zeros([im1_.shape[0],im1_.shape[1]])
ite = 100; #number of iterations
alpha = 10; #smoothness coefficient
fig,ax = plt.subplots(1,3,figsize=(18,5))
for f,a,t in zip((fx,fy,ft),ax,('$f_x$','$f_y$','$f_t$')):
	h = a.imshow(f,cmap='bwr')
    # a.set_title(t)
	fig.colorbar(h,ax=a)
# plt.show()
kernel_l = np.array([[1./12, 1./6, 1./12],[1./6, 0., 1./6],[1./12, 1./6, 1./12]])

# print(fx[100,100],fy[100,100],ft[100,100])

alpha = 1
ite = 20

for it in range(ite):
	u_avg = filter2(u,kernel_l)
	# u_avg = signal.convolve2d(u, kernel_l, boundary='symm',mode='same') #this method takes more time though
	v_avg = filter2(v,kernel_l)
	gamma = (fx*u_avg + fy*v_avg + ft) / (alpha**2 + fx**2 + fy**2)
	u = u_avg - fx * gamma
	v = v_avg - fy * gamma

# if __name__ == "__main__":
"""
Plot Results
"""
ax = plt.figure().gca()
ax.imshow(im2_,cmap = 'gray')
# plt.scatter(POI[:,0,1],POI[:,0,0])
scale = 3
# print len(v)
step_size = 10
for i in range(0,len(u),step_size):
	for j in range(0,len(v),step_size):
		ax.arrow(j,i, v[i,j]*scale, u[i,j]*scale, color='red')

	# plt.arrow(POI[:,0,0],POI[:,0,1],0,-5)

# plt.draw();
# plt.pause(0.01)
plt.show()


import numpy as np
import rnn_fxpts as rfx

np.set_printoptions(linewidth=1000)

N = np.random.randint(128) # arbitrary number of neurons (within reason)
W = np.random.randn(N,N) # arbitrary connection weight matrix
v = np.random.randn(N,1) # arbitrary neural state
v_new = np.tanh(W.dot(v)) # activation rule

N = 2
W = 1.25*np.eye(N) + 0.1*np.random.randn(N,N)
print('>>> W')
print(repr(W))
fxpts, _ = rfx.run_solver(W)
print('>>> fxpts')
print(repr(fxpts))

residual_error = np.tanh(W.dot(fxpts)) - fxpts
print('>>> residual_error')
print(repr(residual_error))

is_fixed, error_margin = rfx.fixed_within_eps(W, fxpts)
print('>>> error_margin')
print(repr(error_margin))
print('>>> np.fabs(residual_error) < error_margin')
print(repr(np.fabs(residual_error) < error_margin))
print('>>> is_fixed')
print(repr(is_fixed))

fxpts, fiber = rfx.run_solver(W)
print('>>> fiber[:,:10]')
print(repr(fiber[:,:10]))

rfx.show_fiber(W, fxpts, fiber)
# rfx.show_fiber(W, fxpts, fiber, savefile='dfiber1.png')

fxpts, fiber = rfx.run_solver(W, c = np.ones((N,1)))
rfx.show_fiber(W, fxpts, fiber)
# rfx.show_fiber(W, fxpts, fiber, savefile='dfiber2.png')

W = 1.25*np.eye(N) + 0.1*np.random.randn(N,N)
print('>>> W')
print(repr(W))
pts, _ = rfx.baseline_solver(W, timeout=1)

print('>>> pts.shape[1]')
print(repr(pts.shape[1]))

is_fixed, error_margin = rfx.fixed_within_eps(W, pts[:,:5])
print('>>> np.tanh(W.dot(pts[:,:5]))-pts[:,:5]')
print(repr(np.tanh(W.dot(pts[:,:5]))-pts[:,:5]))
print('>>> error_margin')
print(repr(error_margin))
print('>>> is_fixed')
print(repr(is_fixed))

pts, converged = rfx.refine_pts(W, pts)
_, error_margin = rfx.fixed_within_eps(W, pts[:,:5])
print('>>> np.tanh(W.dot(pts[:,:5]))-pts[:,:5]')
print(repr(np.tanh(W.dot(pts[:,:5]))-pts[:,:5]))
print('>>> error_margin')
print(repr(error_margin))
print('>>> converged[:5]')
print(repr(converged[:5]))

fxpts = pts[:,converged]
unique_fxpts = rfx.get_unique_fxpts(W, fxpts)
print('>>> fxpts.shape[1]')
print(repr(fxpts.shape[1]))
print('>>> unique_fxpts.shape[1]')
print(repr(unique_fxpts.shape[1]))

unique_fxpts, _ = rfx.post_process_fxpts(W, pts)
print('>>> unique_fxpts')
print(repr(unique_fxpts))


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

def costFunction(theta, x, y):
    import numpy as np
    x_row, x_col = np.shape(x)
    sum_l = 0.0
    from ex2_logistic_regression.sigmoid import sigmoid
    for r in range(x_row):
        cost_row = sigmoid(theta.dot(x[r]))
        y_row = y[r]
        sum_l += (-y_row) * np.log(cost_row) - (1 - y_row) * np.log(1 - cost_row)
    return sum_l / x_row

def costFunction_2(theta, x, y):
    import numpy as np
    from ex2_logistic_regression.sigmoid import sigmoid
    m, n = x.shape
    theta = theta.reshape((n, 1))
    y = y.reshape((m, 1))
    term1 = np.log(sigmoid(x.dot(theta)))
    term2 = np.log(1 - sigmoid(x.dot(theta)))
    term1 = term1.reshape((m, 1))
    term2 = term2.reshape((m, 1))
    term = y * term1 + (1 - y) * term2
    return -((np.sum(term)) / m)

def compute_grad(theta, x, y):
    import numpy as np
    x_row, x_col = np.shape(x)
    from ex2_logistic_regression.sigmoid import sigmoid
    grad = [0] * x_col
    for r in range(x_row):
        cost_row = sigmoid(theta.dot(x[r]))
        y_row = y[r]
        for c in range(x_col):
            grad[c] += ((cost_row - y_row) * x[r][c])

    grad = np.asarray(grad) / x_row
    return grad

def compute_grad_2(theta, x, y):
    import numpy as np
    x_row, x_col = np.shape(x)
    theta = theta.reshape((x_col, 1))
    y = y.reshape((x_row, 1))
    from ex2_logistic_regression.sigmoid import sigmoid
    sigmoid_x_theta = sigmoid(x.dot(theta))
    grad = (x.T.dot(sigmoid_x_theta - y)) / x_row
    return grad.flatten()


import numpy as np
import matplotlib.pyplot as plt

from data import data_matrix, mask_matrix, eval_loss

def shrinkage_threshold(x, gamma):
    """
    Applies the shrinkage/soft-threshold operator given a vector and a threshold.
    It's defined in the equation 1.5 in the paper of FISTA.

    Input:
        x: vector to apply the soft-threshold operator.
        gamma: threshold.
    Output:
        x_out: vector after applying the soft-threshold operator.
    """
    return np.sign(x) * np.maximum(np.abs(x) - gamma, 0)

def singular_value_shrinkage(X, gamma):
    """
    Performs the called singular value shrinkage defined
        in the equation 2.11 from the report.

    Input:
        X: matrix to apply the singular value shrinkage operator.
        gamma: threshold.
        newshape: (optional) if we need to reshape the input (e.g. a vector),
            we can pass a new shape.
    Output:
        X_out: matrix after applying the singular value shrinkage operator.
    """

    U, s, VT = np.linalg.svd(X, full_matrices=True)
    s_th = shrinkage_threshold(s, gamma)

    S = np.zeros_like(X)
    np.fill_diagonal(S, s_th)

    return (U @ S @ VT)

def fista(X, O, i_eval=10, gamma=1, t_k=1, L_hat=0.5, n_iter=2):
    """
    Performs the Fast Iterative Shrinkage-Thresholding Algorithm (FISTA) defined
        in the paper of FISTA adapted to the problem of matrix completion.

    Input:
        X: noisy matrix.
        A: matrix that encodes the known entries
        gamma: threshold for the singular value shrinkage operator.
        n_iter: Number of iteration that the algorithm executes.

    Output:
        Y_k: reconstructed matrix after n_iter iterations of the algorithm.
    """

    X_k = X.copy()
    Y_k = X.copy()

    gamma = gamma / (1 / L_hat)

    solutions = []
    for i in range(n_iter):

        X_kk = singular_value_shrinkage(Y_k + L_hat * O * (X - Y_k), gamma)

        t_kk = (1 + np.sqrt(1 + 4 * t_k ** 2)) / 2

        Y_k = X_kk + ((t_k - 1) / t_kk) * (X_kk - X_k)

        X_k = X_kk
        t_k = t_kk

        if i % i_eval == 0:
            solutions.append(Y_k)

    solutions.append(Y_k)

    return solutions

def main_first_order():

    n_iter = 5000

    M = data_matrix()
    O = mask_matrix()
    X = M * O

    fig, ax = plt.subplots()

    for gamma in [0.5, 0.1, 0.01, 0.001]:

        solutions = fista(X, O, gamma=gamma, n_iter=n_iter)
        losses = [eval_loss(M, M_hat) for M_hat in solutions]

        print("Min loss:", losses[-1])

        ax.plot(losses, label=f"$\gamma = {{{gamma}}}$")

    ax.set_xticks(np.linspace(0, len(losses), 6, dtype=int))
    ax.set_xticklabels(np.linspace(1, n_iter, 6, dtype=int))
    ax.set_xlabel("Epoch")
    ax.set_ylabel("Loss")
    ax.spines["top"].set_visible(False)
    ax.spines["right"].set_visible(False)

    ax.axhline(y=0.3382029640059954, linestyle="--", c="maroon",
               label=r"CVXPY ($\gamma = 0.01$)", alpha=0.7)

    plt.legend()
    plt.savefig("loss_approx.pdf")

if __name__ == "__main__":
    main_first_order()


#utility.py
import math
import numpy as np

def vec2trans_2d(vec):
    x = vec[0]
    y = vec[1]
    theta = float(vec[2])

    T = np.zeros((3,3))
    T[0,2] = round(float(x), 3)
    T[1,2] = round(float(y), 3)
    T[2,2] = 1

    T[0,0] = math.cos(theta)
    T[0,1] = -math.sin(theta)
    T[1,0] = math.sin(theta)
    T[1,1] = math.cos(theta)

    return T

def trans2vec_2d(T, return_type=None):
    x = T[0,2]
    y = T[1,2]

    theta = math.atan2(T[1,0], T[0,0])

    if return_type == 'numpy':
        return np.array([x,y,theta])
    elif return_type == 'list':
        return [x,y,theta]
    else:
        return x,y,theta

def angle2mat_2d(theta):
    R = np.array([  [math.cos(theta), -math.sin(theta)],
                    [math.sin(theta), math.cos(theta)] ])

    return R

# keep angles between -pi to pi
def limit_angles(theta):
    if theta > np.pi:
        delta = theta - np.pi
        return -(np.pi - delta)
    elif theta < -np.pi:
        delta = abs(theta) - np.pi
        return np.pi - delta
    else:
        return theta

# this function expects vertex and edges
# vertex format:{"frame_1":frame, "measurement":[x,y,theta]}
# edges format :{"frame_1":ref_frame, "frame_2":frame, "measurement":[del_x, del_y, del_theta], "info_mat":np.array: 3x3 }
def write_g2o_file(filename, vertex, edges):
    g2o_file = open(filename, 'w+')

    for frame in vertex:
        line = "VERTEX_SE2 " + str(frame) + " " + str(vertex[frame][0]) + " " + str(vertex[frame][1]) + " " + str(vertex[frame][2]) + '\n'
        g2o_file.write(line)

    for frame in edges:
        for edge in edges[frame]:
            frame_1 = edge["frame_1"]
            frame_2 = edge["frame_2"]

            measurement = edge["measurement"]

            infor_mat = edge["info_mat"]
            info_mat_txt = str(infor_mat[0,0])
            info_mat_txt += " " + str(infor_mat[0,1])
            info_mat_txt += " " + str(infor_mat[0,2])
            info_mat_txt += " " + str(infor_mat[1,1])
            info_mat_txt += " " + str(infor_mat[1,2])
            info_mat_txt += " " + str(infor_mat[2,2])

            line = "EDGE_SE2 " + str(frame_1) + " " + str(frame_2) + " " + str(measurement[0]) + " " + str(measurement[1]) + " " + str(measurement[2]) + " " + info_mat_txt + '\n'
            g2o_file.write(line)

    g2o_file.close()

def create_vertex_from_state_vector(state_vector):
    state_vector = list(state_vector)

    vertex = {}

    for i,vec in enumerate(state_vector):
        vec = list(vec)
        vertex[str(i)] = vec

    return vertex


# https://www.hackerrank.com/challenges/np-linear-algebra/problem

import numpy

# Inputs
standard_input = """2
1.1 1.1
1.1 1.1"""

n = int(input())
# 2

a = numpy.array([input().split() for _ in range(n)], float)
# 1.1 1.1
# 1.1 1.1

numpy.set_printoptions(legacy="1.13")
print(numpy.linalg.det(a))
# 0.0

""" Reference

[linalg.det]

The linalg.det tool computes the determinant of an array.

print(numpy.linalg.det([[1, 2], [2, 1]]))
# -3.0

[linalg.eig]

The linalg.eig computes the eigenvalues and right eigenvectors of a square array.

vals, vecs = numpy.linalg.eig([[1, 2], [2, 1]])

print(vals)
# [ 3. -1.]
print(vecs)
# [[ 0.70710678 -0.70710678]
#  [ 0.70710678  0.70710678]]

[linalg.inv]

The linalg.inv tool computes the (multiplicative) inverse of a matrix.

print(numpy.linalg.inv([[1, 2], [2, 1]]))
# [[-0.33333333  0.66666667]
#  [ 0.66666667 -0.33333333]]

"""

__Training__/Python - HackerRank/16. Numpy/Linear Algebra.py


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

def normal_distribution(mean=0, sigma=1, samples=1):
    return np.random.normal(mean, sigma, samples)

def get_cumulative_data(data, func):
    return [func(data[:i]) for i in range(1, len(data) - 1)]

def get_cumulative_mean_and_variance(data):
    return get_cumulative_data(data, np.mean), get_cumulative_data(data, np.var)

def visualize_gaussian_distributions(means, sigmas, samples):
    data = np.zeros(shape=(len(means), samples))
    for i in range(len(means)):
        data[i, :] = normal_distribution(means[i], sigmas[i], samples)

    data = np.sum(data, axis=0)

    ax_0 = sns.distplot(data)
    ax_0.set_title('Gaussian Distribution with parameters: mean = {}, sigma = {}'.format(means, sigmas))
    ax_0.set_xlabel('x')
    ax_0.set_ylabel('y')
    plt.show()

    cumulative_means, cumulative_variances = get_cumulative_mean_and_variance(data)
    f, (ax1, ax2) = plt.subplots(nrows=1, ncols=2, sharey=True)

    ax1.set_title('Mean depends on samples.')
    ax1.set_xlabel('Number of samples')
    ax1.set_ylabel('Mean')
    ax1.axhline(y=np.sum(means), color='red')
    ax1.plot(cumulative_means)

    ax2.set_title('Variance depends on samples.')
    ax2.set_xlabel('Number of samples')
    ax2.set_ylabel('Variance')
    ax2.plot(cumulative_variances)
    ax2.axhline(y=np.sum([x ** 2 for x in sigmas]), color='red')
    plt.show()

visualize_gaussian_distributions(means=[0,2,0, 4], sigmas=[2, 0.5, 1,12], samples=5000)
# visualize_gaussian_distributions(means=[5, 10], sigmas=[1, 1], samples=5000)
# visualize_gaussian_distributions(means=[5, 10], sigmas=[1, 1], samples=5000)


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

"""Autocorrelation function of a *finite* sine wave.

Autocorrelation function of a finite sine wave over n cycles is:

  r(tau) = [(2*n*pi - tau)*cos(tau) + sin(tau)] / 2*n*pi

As n -> infinity, r(tau) = cos(tau) as expected.
"""

import numpy as np
import matplotlib.pyplot as plt
from nolitsa import delay

n = 2 ** 3
t = np.linspace(0, n * 2 * np.pi, n * 2 ** 10)
x = np.sin(t)

r = delay.acorr(x)
r_exp = (((2 * n * np.pi - t) * np.cos(t) + np.sin(t)) / (2 * n * np.pi))

plt.title(r'Autocorrelation of a finite sine wave')
plt.xlabel(r'$t$')
plt.ylabel(r'$r(t)$')
plt.plot(t[::25], r[::25], 'o', label='Numerical')
plt.plot(t, r_exp, label='Theoretical')

plt.legend()
plt.show()


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sat Feb  9 12:27:27 2019

@author: alankar
"""

import numpy as np

def simpson(func, a, b, n,*args):
    h=(b-a)/n
    k=0.0
    x=a + h
    for i in range(1,int(n/2) + 1):
        k += 4*func(x,*args)
        x += 2*h

    x = a + 2*h
    for i in range(1,int(n/2)):
        k += 2*func(x,*args)
        x += 2*h
    return (h/3)*(func(a,*args)+func(b,*args)+k)

f = lambda x:np.sin(np.sqrt(100*x))**2

tol = 1e-6

n = 1
I_old = 0
I_new = simpson(f,0,1,n)

print('SIMPSON INTEGRATION: ')
while (abs(I_new-I_old)>tol):
    n *= 2
    print('Slices = %d'%n)
    I_old = I_new
    I_new = simpson(f,0,1,n)
    print('I = %.7f'%I_new)
    print('Fractional error estimate: %e'%abs((I_new-I_old)/I_new))


import numpy as np

def euclidean_distance(x1, x2):
    d = np.sqrt(np.sum((x1 - x2) ** 2, axis=1))
    return d

def manhattan_distance(x1, x2):
    d = np.sum(np.abs(x1 - x2), axis=1)
    return d


from __future__ import annotations

import numpy as np
from numpy.linalg import inv, det, slogdet

class UnivariateGaussian:
    """
    Class for univariate Gaussian Distribution Estimator
    """

    def __init__(self, biased_var: bool = False) -> UnivariateGaussian:
        """
        Estimator for univariate Gaussian mean and variance parameters

        Parameters
        ----------
        biased_var : bool, default=False
            Should fitted estimator of variance be a biased or unbiased estimator

        Attributes
        ----------
        fitted_ : bool
            Initialized as false indicating current estimator instance has not been fitted.
            To be set as True in `UnivariateGaussian.fit` function.

        mu_: float
            Estimated expectation initialized as None. To be set in `UnivariateGaussian.fit`
            function.

        var_: float
            Estimated variance initialized as None. To be set in `UnivariateGaussian.fit`
            function.
        """
        self.biased_ = biased_var
        self.fitted_, self.mu_, self.var_ = False, None, None

    def fit(self, X: np.ndarray) -> UnivariateGaussian:
        """
        Estimate Gaussian expectation and variance from given samples
        Parameters
        ----------
        X: ndarray of shape (n_samples, )
            Training data

        Returns
        -------
        self : returns an instance of self.

        Notes
        -----
        Sets `self.mu_`, `self.var_` attributes according to calculated estimation (where
        estimator is either biased or unbiased). Then sets `self.fitted_` attribute to `True`
        """
        if self.biased_:  # ddof set to 0 - MLE of variance which is biased
            self.var_ = np.var(X)
        else:  # ddof set to 1 - unbiased estimator of var
            self.var_ = np.var(X, ddof=1)
        self.mu_ = np.mean(X)
        self.fitted_ = True
        return self

    def pdf(self, X: np.ndarray) -> np.ndarray:
        """
        Calculate PDF of observations under Gaussian model with fitted estimators

        Parameters
        ----------
        X: ndarray of shape (n_samples, )
            Samples to calculate PDF for

        Returns
        -------
        pdfs: ndarray of shape (n_samples, )
            Calculated values of given samples for PDF function of N(mu_, var_)

        Raises
        ------
        ValueError: In case function was called prior fitting the model
        """
        if not self.fitted_:
            raise ValueError("Estimator must first be fitted before calling `pdf` function")
        res = X.copy()
        cnt = 0
        for sample in X:
            res[cnt] = self.__calc_gauss(sample, self.var_, self.mu_)
            cnt += 1

        return res

    @staticmethod
    def __calc_gauss(x_i, variance, mu):

        sd = np.sqrt(variance)
        a = 1 / np.sqrt(2 * np.pi * variance)
        b = (((x_i - mu) / sd) ** 2)
        c = np.exp(-0.5 * b)
        return a * c

    @staticmethod
    def log_likelihood(mu: float, sigma: float, X: np.ndarray) -> float:
        """
        Calculate the log-likelihood of the data under a specified Gaussian model

        Parameters
        ----------
        mu : float
            Expectation of Gaussian
        sigma : float
            Variance of Gaussian
        X : ndarray of shape (n_samples, )
            Samples to calculate log-likelihood with

        Returns
        -------
        log_likelihood: float
            log-likelihood calculated
        """
        # var = sigma * sigma // written in the moodle that sigma is variance, although conventionally it is SD
        res = 0
        for x_i in X:
            res += np.log(UnivariateGaussian.__calc_gauss(x_i, sigma, mu))
        return res

class MultivariateGaussian:
    """
    Class for multivariate Gaussian Distribution Estimator
    """

    def __init__(self):
        """
        Initialize an instance of multivariate Gaussian estimator

        Attributes
        ----------
        fitted_ : bool
            Initialized as false indicating current estimator instance has not been fitted.
            To be set as True in `MultivariateGaussian.fit` function.

        mu_: ndarray of shape (n_features,)
            Estimated expectation initialized as None. To be set in `MultivariateGaussian.fit`
            function.

        cov_: ndarray of shape (n_features, n_features)
            Estimated covariance initialized as None. To be set in `MultivariateGaussian.fit`
            function.
        """
        self.mu_, self.cov_ = None, None
        self.fitted_ = False

    @staticmethod
    def __calc_mult_pdf(x_i, cov, mu, d):
        a = 1 / (np.sqrt(((2 * np.pi) ** d) * det(cov)))
        xi_i_mu = (x_i - mu)
        cov_inverted = inv(cov)
        p = -0.5 * np.matmul((np.matmul(xi_i_mu.T, cov_inverted)), xi_i_mu)
        res = a * np.exp(p)
        return res

    def fit(self, X: np.ndarray) -> MultivariateGaussian:
        """
        Estimate Gaussian expectation and covariance from given samples

        Parameters
        ----------
        X: ndarray of shape (n_samples, n_features)
            Training data

        Returns
        -------
        self : returns an instance of self

        Notes
        -----
        Sets `self.mu_`, `self.cov_` attributes according to calculated estimation.
        Then sets `self.fitted_` attribute to `True`
        """
        # raise NotImplementedEror()
        self.mu_ = np.mean(X, axis=0)
        self.cov_ = np.cov(X, rowvar=False)
        self.fitted_ = True
        return self

    def pdf(self, X: np.ndarray):
        """
        Calculate PDF of observations under Gaussian model with fitted estimators

        Parameters
        ----------
        X: ndarray of shape (n_samples, n_features)
            Samples to calculate PDF for

        Returns
        -------
        pdfs: ndarray of shape (n_samples, )
            Calculated values of given samples for PDF function of N(mu_, cov_)

        Raises
        ------
        ValueError: In case function was called prior fitting the model
        """
        if not self.fitted_:
            raise ValueError("Estimator must first be fitted before calling `pdf` function")
        pdfs = []
        d = X.shape[1]  # n_features
        cnt = 0
        for x in X:
            pdfs[cnt] = MultivariateGaussian.__calc_mult_pdf(x, self.cov_, self.mu_, d)
            cnt += 1
        return pdfs

    @staticmethod
    def log_likelihood(mu: np.ndarray, cov: np.ndarray, X: np.ndarray) -> float:
        """
        Calculate the log-likelihood of the data under a specified Gaussian model

        Parameters
        ----------
        mu : ndarray of shape (n_features,)
            Expectation of Gaussian
        cov : ndarray of shape (n_features, n_features)
            covariance matrix of Gaussian
        X : ndarray of shape (n_samples, n_features)
            Samples to calculate log-likelihood with

        Returns
        -------
        log_likelihood: float
            log-likelihood calculated over all input data and under given parameters of Gaussian
        """

        x_mu_sig = np.sum((X-mu) @ inv(cov) * (X-mu))
        d = mu.shape[0]
        m = X.shape[0]
        almost = m * np.log((2 * np.pi) ** d * det(cov))
        final = -0.5 * (x_mu_sig + almost)
        return final


import numpy as np
import matplotlib.pyplot as plt
import math
def equationGraph(formula : str, x_range : int, tick_n):
	x = np.array(x_range)
	y = eval(formula)
	plt.plot(x, y)
	plt.xticks(np.arange(min(x), max(x)+1, tick_n))
	plt.grid(True)
	plt.savefig('test.png')

def commonOnotations():
	x = np.array(range(1, 12))
	y = [
		np.log(x),
		x,
		x*np.log(x),
		x**2,
		x**3,
		2**x,

	]
	labels = [
		"LOG N",
		"N",
		"N LOG N",
		"N^2",
		"N^3",
		"2^N"
	]
	for i, label in zip(y, labels):
		plt.plot(x, i, label=f"O({label})")

	plt.xticks(np.arange(min(x), max(x)+1, 10.0))
	plt.ylabel('Steps')
	plt.xlabel('Items')
	plt.grid(True)
	plt.legend()
	plt.savefig('onotation.png')
def exact_probability(trials : int, successes : int, chance : float) -> float:
	coeff = coefficient(trials, successes)
	pow_probability = chance**successes
	pow_probability_2 = (1-chance)**(trials-successes)
	probability_out = coeff*pow_probability*pow_probability_2
	return probability_out
def coefficient(trials : int, successes : int) -> float:
	if(successes > trials - successes):
		successes = trials-successes
	res = 1
	for i in range(successes):
		res = res * (trials - i)
		res = res / (i + 1)
	return res
def atleast_number_of_success_probability(trials, successes, chance):
	complementary = 0
	for i in range(successes):
		complementary += exact_probability(trials, i, chance)
	return 1-complementary
def trials_to_reach_probability(successes : int, chance : float, desired_probability : float):
	finished = False
	trials = successes
	while not finished:
		calculate_probability = atleast_number_of_success_probability(trials, successes, chance)
		if calculate_probability >= desired_probability:
			finished = True
			return calculate_probability, trials
		else:
			trials += 1
def pythagoras(a=None, b=None, c=None) -> float:
	#c = a + b
	#b = c - a
	#a = c - b
	if a and b:
		return math.sqrt(math.pow(a,2)+math.pow(b,2))
	elif c and a:
		return math.sqrt(math.pow(c,2)-math.pow(a,2))
	elif c and b:
		return math.sqrt(math.pow(c,2)-math.pow(b,2))
	return None
if __name__ == "__main__":
	print(commonOnotations())


import numpy as np
import logging
import time
import matplotlib.pyplot as plt

class adam_SGD:
    def __init__(
        self,
        alpha: float = 0.001,
        beta_1: float = 0.9,
        beta_2: float = 0.999,
        k: float = 1e-8,
        eps: float = 1e-6,
        max_feval: int = 10000,
        plot: bool = False,
        verbose:bool = False
    ):

        self.alpha = alpha
        self.beta_1 = beta_1
        self.beta_2 = beta_2
        self.k = k
        self.eps = eps
        self.max_feval = max_feval
        self.f = None
        self.x = None
        self.feval = 0
        self.g = None
        self.f_value = None
        self.plot = plot
        self.verbose = verbose
        self.start_time = None
        self.time_evaluations = []

    def plot_fvalues(self):
        plt.plot(self.f_values)
        plt.yscale("log")
        plt.xlabel("f evaluations")

        plt.ylabel("Model Loss")
        plt.show()

    def solve(self, f, x):
        self.f = f
        self.x = x
        self.f_values = []
        status = None
        m_t = np.zeros_like(x)
        v_t = np.zeros_like(x)
        self.f_value, self.g = f(x)
        self.start_time = time.process_time()
        ng = np.linalg.norm(self.g)
        ng0 = ng

        row = ["f value","delta f_v", "g norm", "f_evals"]
        _log_infos(row)

        while(True): #till it gets converged
            self.feval += 1
            new_f_value, self.g = f(x)
            self.f_values.append(new_f_value)
            current_time = time.process_time()
            self.time_evaluations.append(current_time-self.start_time)
            m_t = self.beta_1 * m_t + (1-self.beta_1)*self.g
            v_t = self.beta_2 * v_t + (1-self.beta_2)*np.multiply(self.g,self.g)
            m_hat = m_t/(1-self.beta_1**(self.feval+1))
            v_hat = v_t/(1-self.beta_2**(self.feval+1))
            x = x - self.alpha*np.multiply(m_hat,1/(np.sqrt(v_hat+self.k)))
            ng = np.linalg.norm(self.g)
            ### log infos
            row = []
            row.append(f"{self.f_value:1.3E}")
            row.append(f"{new_f_value-self.f_value:1.3E}")
            row.append(f"{ng:1.3E}")
            row.append(f"{self.feval}")
            _log_infos(row)
            ###

            if self.feval > self.max_feval:
                status = "optimal"
                #status = "stopped for reached max_feval"
                break

            #UPDATE ITERATES
            self.f_value = new_f_value

        if self.plot:
            self.plot_fvalues()

        if(self.verbose):
            print(f"f min reached: \t{min(self.f_values)}")
        return status

def _log_infos(row):
    string = "{: >15} {: >15} {: >15} {: >10}".format(*row)
    logging.info(string)


from sympy import *

def deg2rad(angle):
    """
    Converts degrees to radians

    Parameters
    ----------
    angle : float, int
        Angle in degrees

    Returns
    -------
    ar : float
        Angle in radians

    Examples
    --------
    >>> deg2rad(30)
    0.523598775598299
    >>> deg2rad(90)
    1.57079632679490
    >>> deg2rad(180)
    3.14159265358979
    """
    ar = ( (angle)*(pi/180) ).evalf()
    return ar

def rad2deg(angle):
    """
    Converts radians to degrees

    Parameters
    ----------
    angle : float, int
        Angle in radians

    Returns
    -------
    ad : float
        Angle in radians

    Examples
    --------
    >>> rad2deg(pi)
    180.000000000000
    >>> rad2deg(pi/2)
    90.0000000000000
    >>> rad2deg(2*pi)
    360.000000000000

    """
    ad = ( (angle)*(180/pi) ).evalf()
    return ad

if __name__=="__main__":
    print(deg2rad(90))
    print(rad2deg(pi/4))


import numpy as np
import os
import json

def make_translation(X, Y, Z):
    ''' Make translation matrix '''
    T = np.matrix(
    [
        [1, 0, 0, -X],
        [0, 1, 0, -Y],
        [0, 0, 1, -Z],
        [0, 0, 0, 1]
    ]
    )
    return T

def make_location(X, Y, Z):
    T = np.matrix(
    [
        [X],
        [Y],
        [Z]
    ])
    return T

def make_rotation(pitch, yaw, roll):
    # Convert from degree to radius
    pitch = pitch / 180.0 * np.pi
    yaw = yaw / 180.0 * np.pi
    roll = roll / 180.0 * np.pi
    pitch = -pitch
    yaw = yaw # ???!!!
    roll = -roll # Seems UE4 rotation direction is different
    # from: http://planning.cs.uiuc.edu/node102.html
    ryaw = [
        [np.cos(yaw), -np.sin(yaw), 0, 0],
        [np.sin(yaw), np.cos(yaw), 0, 0],
        [0, 0, 1, 0],
        [0, 0, 0, 1]
    ]
    rpitch = [
        [np.cos(pitch), 0, np.sin(pitch), 0],
        [0, 1, 0, 0],
        [-np.sin(pitch), 0, np.cos(pitch), 0],
        [0, 0, 0, 1]
    ]
    rroll = [
        [1, 0, 0, 0],
        [0, np.cos(roll), -np.sin(roll), 0],
        [0, np.sin(roll), np.cos(roll), 0],
        [0, 0, 0, 1]
    ]
    T = np.matrix(ryaw) * np.matrix(rpitch) * np.matrix(rroll)
    return T

def make_rearrage():
    return np.matrix(
        [[0, 1, 0, 0],
        [0, 0, -1, 0],
        [1, 0, 0, 0],
        [0, 0, 0, 1]
        ]
    )

def make_intrinsic(fx, fy, cx, cy):
    return np.matrix(
        [[fx, 0, cx, 0],
        [0, fy, cy, 0],
        [0, 0, 1, 0],
        [0, 0, 0, 0]
        ])

class CameraPose:
    def __init__(self, x, y, z, pitch, yaw, roll, width, height, f):
        self.x, self.y, self.z = x, y, z
        self.pitch, self.yaw, self.roll = pitch, yaw, roll
        self.width, self.height, self.f = width, height, f
        # with open(os.path.join(meta_dir, 'camera_parameter.json'), 'r') as file:
        #     obj = json.load(file)
        #     self.fx, self.fy = obj[img_type]['FocalLength']
        #     self.px, self.py = obj[img_type]['PrincipalPoint']

    def __repr__(self):
        print(self.__dict__)
        return 'x:{x} y:{y} z:{z} pitch:{pitch} yaw:{yaw} roll:{roll} width:{width} height:{height} f:{f}'.format(**self.__dict__)

    # The points_3d is in the canonical coordinate
    def project_to_2d(self, points_3d):
        '''
        points_3d: points in 3D world coordinate, n * 3
        cam_pose: camera pose
        '''
        if not points_3d.shape[1] == 3:
            print('The input shape is not n x 3, but n x %d' % points_3d.shape[1])
            # TODO: replace this with logging
            return

        npoints = points_3d.shape[0]
        points_3d = np.concatenate((points_3d, np.ones((npoints, 1))), axis = 1)

        cam_T = make_translation(self.x, self.y, self.z)
        cam_R = make_rotation(self.pitch, self.yaw, self.roll)

        world_to_camera = cam_R.T * cam_T # inverse matrix
        points_3d_camera = (make_rearrage() * world_to_camera * points_3d.T).T

        # TODO: Need to fix this
        #half_width = self.width / 2
        #half_height = self.height / 2
        px = self.width / 2
        py = self.height / 2

        n_points = points_3d.shape[0]
        points_2d = np.zeros((n_points, 2))

        #points_2d[:,0] = (points_3d_camera[:,1] / points_3d_camera[:,0] * self.fx + self.px).squeeze()
        #points_2d[:,1] = (- (points_3d_camera[:,2]) / points_3d_camera[:,0] * self.fy + self.py).squeeze()

        points_2d[:,0] = (points_3d_camera[:,0] / points_3d_camera[:,2] * self.f + px).squeeze()
        points_2d[:,1] = ((points_3d_camera[:,1]) / points_3d_camera[:,2] * self.f + py).squeeze()

        return points_2d

The container /Robotic Arm/craves.ai-master/unreal/virtual_db/d3.py


import numpy as np

def npCI(data,
         q,
         sigma=1.96,
         assume_sorted=False):
    ''' Implements non-parametric intervals for quantiles following
        "Confidence interval for quantiles and percentiles,
         Cristiano Ialongo,  doi: 10.11613/BM.2019.010101"

        data : array of observasions
        q: Percentile or sequence of percentiles
        to compute uncertainties for
        assume_sorted = False : If True the data are assumed
        to be sorted
        sigma = 1.96 : standarized quantile Z_(a/2)
        for confidence level

        return lower,upper arrays

        Note : Can be inaccurate for extreme quantiles
    '''
    if assume_sorted:
        _data = data
    else:
        _data = np.sort(data)

    _n = len(_data)
    _l_indices = np.floor(
        (_n*q) - sigma * np.power(_n*q*(1.-q), 0.5)).astype('int') - 1
    _u_indices = np.ceil(
        (_n*q) + sigma * np.power(_n*q*(1.-q), 0.5)).astype('int') - 1
    _l_indices = np.clip(_l_indices, 0, len(_data)-1)
    _u_indices = np.clip(_u_indices, 0, len(_data)-1)
    return data[_l_indices], data[_u_indices]


import matplotlib.pyplot as plt
import numpy as np
from plotting import *

def PID(x,I,dx,KP,KI,KD):
    u = -np.dot(KP,x)-np.dot(KI,I)-np.dot(KD,dx)
    return u

def PID_trajectory(A,B,c,D,x0,dx0,KP,KI,KD,dt=1e-3,T=10,xdes=None,dxdes=None):
    """
    For 2nd order system Ax + Bdx + c + Du and PID controller
    Returns dictionary of trajectories
    [t(t), x(t), I(t), dx(t), ddx(t), u(t), uP(t), uI(t), uD(t)]"""
    x = x0.copy()
    dx = dx0.copy()
    I = np.zeros(len(x0))
    res = dict((idx,[]) for idx in ['t','xdes','dxdes','x','I','dx','ddx','u','uP','uI','uD'])
    t = 0
    while t < T:
        xd = xdes(t) if xdes is not None else np.zeros(len(x0))
        dxd = dxdes(t) if dxdes is not None else np.zeros(len(x0))
        u = PID(x-xd,I,dx-dxd,KP,KI,KD)
        ddx = np.dot(A,x-xd) + np.dot(B,dx-dxd) + c + np.dot(D,u)
        res['t'].append(t)
        res['x'].append(x.copy())
        if xdes is not None:
            res['xdes'].append(xd)
        if dxdes is not None:
            res['dxdes'].append(dxd)
        res['I'].append(I)
        res['dx'].append(dx.copy())
        res['u'].append(u)
        res['ddx'].append(ddx.copy())
        res['uP'].append(-np.dot(KP,x-xd))
        res['uD'].append(-np.dot(KD,dx-dxd))
        res['uI'].append(-np.dot(KI,I))
        I += dt*(x-xd)
        t += dt
        x += dx*dt
        dx += ddx*dt
    return res

A=np.zeros((2,2))
A[1,0] = 0.4
A[0,1] = -0.4
B=np.zeros((2,2))
B[1,0] = 0
B[0,1] = -0
c=np.zeros(2)
#c[1] = 0.5
D=np.eye(2)*1
x0=np.array([1.,0.])
dx0=np.array([0.,0.])
res1 = PID_trajectory(A,B,c,D,x0=x0,dx0=dx0,KP=np.eye(2)*1,KI=np.eye(2)*0.25,KD=np.eye(2)*2,dt=0.01,T=20)
res2 = PID_trajectory(A,B,c,D,x0=x0,dx0=dx0,KP=np.eye(2)*1,KI=np.eye(2)*0.25,KD=np.eye(2)*1,dt=0.01,T=20)
res3 = PID_trajectory(A,B,c,D,x0=x0,dx0=dx0,KP=np.eye(2)*1,KI=np.eye(2)*0.25,KD=np.eye(2)*0.5,dt=0.01,T=20)
#plotmulti([res1,res1],['x','x'],['x','x'],[0,1],['black','green','red','blue'])
plt.figure(figsize=(6,6))
plotxy([res1,res2,res3],['kD=2','kD=1','kD=0.5'],['x','x','x'],[0,1],['black','green','red','blue'])
#plotxy([res1,res1],['x','u'],['x','u'],[0,1],['black','green','red','blue'])
plt.show()


'''
The degree centrality of a node v is the fraction of nodes it is connected to.

The degree centrality values are normalized by dividing by the maximum possible degree in a simple graph n-1 where n is the number of nodes in G.

For multigraphs or graphs with self loops the maximum degree might be higher than n-1 and values of degree centrality greater than 1 are possible.
'''

import networkx as nx

def calculate(net):
    try:
        n = nx.degree_centrality(net)
    except:
        return 0

    if len(n.values()) == 0:
        return 0
    else:
        return round(sum(n.values())/len(n.values()), 7)


"""
## =========================================================================== ##
MIT License
Copyright (c) 2021 Roman Parak
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
## =========================================================================== ##
Author   : Roman Parak
Email    : Roman.Parak@outlook.com
Github   : https://github.com/rparak
File Name: Bezier.py
## =========================================================================== ##
"""

# Numpy (Array computing) [pip3 install numpy]
import numpy as np

# Support for type hints
import typing

# Initialization of constants
CONST_NUM_OF_ENTRY_POINTS_LINEAR    = 2
CONST_NUM_OF_ENTRY_POINTS_QUADRATIC = 3
CONST_NUM_OF_ENTRY_POINTS_CUBIC     = 4
# Time t ∈ [0: The starting value of the sequence,
#           1: The end value of the sequence]
CONST_T_START = 0
CONST_T_STOP  = 1

def Linear(num_of_samples: typing.Union[int], points: typing.Union[typing.List[int], typing.List[float]]) -> typing.Union[typing.List[int], typing.List[float]]:
    """
    Description:
        Given two control points p_{0} and p_{1} we define the linear Bézier curve to be the curve parametrized by:

        p(t) = (1 - t)*p_{0} + t*p_{1}, t ∈ [0, 1]

    Args:
        (1) num_of_samples [INT]: Number of samples to generate. Must be non-negative.
        (2) points [p_{0, 1}] [Int/Float Matrix]: Multiple points to create a curve.

    Returns:
        (1) parameter [Int/Float Matrix]: Resulting points of the curve.

    Example:
        res = Linear(num_of_samples, points),
            where points are equal to [[px_id_0, py_id_0], [px_id_1, py_id_1]] in 2D space
            and [[px_id_0, py_id_0, pz_id_0], [px_id_1, py_id_1, pz_id_1]] in 3D space
    """
    try:
        assert len(points) == CONST_NUM_OF_ENTRY_POINTS_LINEAR
        assert(num_of_samples >= 0)

        # Return evenly spaced numbers over a specified interval.
        t = np.linspace(CONST_T_START, CONST_T_STOP, num_of_samples)

        return [(1 - t) * p[0] + t * p[1]
                for _, p in enumerate(np.transpose(points))]

    except AssertionError as error:
        print('[ERROR] Insufficient number of entry points.')
        print('[ERROR] The correct number of entry points is %d.' % CONST_NUM_OF_ENTRY_POINTS_LINEAR)
        print('[ERROR] The number of samples must not be negative.')

def Quadratic(num_of_samples: typing.Union[int], points: typing.Union[typing.List[int], typing.List[float]]) -> typing.Union[typing.List[int], typing.List[float]]:
    """
    Description:
        Given three control points p_{0}, p_{1} and p_{2} we define the quadratic Bézier curve (degree 2 Bézier curve)
        to be the curve parametrized by:

        p(t) = ((1 - t)^2)*p_{0} + 2*t*(1 - t)*p_{1} + (t^2)*p_{2}, t ∈ [0, 1]

    Args:
        (1) num_of_samples [INT]: Number of samples to generate. Must be non-negative.
        (2) points [p_{0, 1, 2}] [Int/Float Matrix]: Multiple points to create a curve.

    Returns:
         (1) parameter [Int/Float Matrix]: Resulting points of the curve.

    Example:
        res = Quadratic(t, p),
            where points are equal to [[px_id_0, py_id_0], [px_id_1, py_id_1], [px_id_2, py_id_2]] in 2D space
            and [[px_id_0, py_id_0, pz_id_0], [px_id_1, py_id_1, pz_id_1], [px_id_2, py_id_2, pz_id_2]] in 3D space
    """

    try:
        assert len(points) == CONST_NUM_OF_ENTRY_POINTS_QUADRATIC
        assert(num_of_samples >= 0)

        # Return evenly spaced numbers over a specified interval.
        t = np.linspace(CONST_T_START, CONST_T_STOP, num_of_samples)

        return [(1 - t)**2 * p[0] + 2 * t * (1 - t) * p[1] + t**2 * p[2]
                for _, p in enumerate(np.transpose(points))]

    except AssertionError as error:
        print('[ERROR] Insufficient number of entry points.')
        print('[ERROR] The correct number of entry points is %d.' % CONST_NUM_OF_ENTRY_POINTS_QUADRATIC)
        print('[ERROR] The number of samples must not be negative.')

def Cubic(num_of_samples: typing.Union[int], points: typing.Union[typing.List[int], typing.List[float]]) -> typing.Union[typing.List[int], typing.List[float]]:
    """
    Description:
        Given four control points p_{0}, p_{1}, p_{2} and p_{3} we define the cubic Bézier curve (degree 3 Bézier curve) to
        be the curve parametrized by:

        p(t) = ((1 - t)^3)*p_{0} + 3*t*((1 - t)^2)*p_{1} + (3*t^2)*(1 - t)*p_{2} + (t^3) * p_{3}, t ∈ [0, 1]

    Args:
        (1) num_of_samples [INT]: Number of samples to generate. Must be non-negative.
        (2) points [p_{0, 1, 2, 3}] [Int/Float Matrix]: Multiple points to create a curve.

    Returns:
        (1) parameter [Int/Float Matrix]: Resulting points of the curve.

    Example:
        res = Cubic(t, p),
            where points are equal to [[px_id_0, py_id_0], [px_id_1, py_id_1], [px_id_2, py_id_2], [px_id_3, py_id_3]] in 2D space
            and [[px_id_0, py_id_0, pz_id_0], [px_id_1, py_id_1, pz_id_1], [px_id_2, py_id_2, pz_id_2], [px_id_3, py_id_3, pz_id_2]] in 3D space
    """
    try:
        assert len(points) == CONST_NUM_OF_ENTRY_POINTS_CUBIC
        assert(num_of_samples >= 0)

        # Return evenly spaced numbers over a specified interval.
        t = np.linspace(CONST_T_START, CONST_T_STOP, num_of_samples)

        return [((1 - t)**3) * (p[0]) + (3 * t * (1 - t)**2) * (p[1]) + 3 * (t**2) * (1 - t) * p[2] + (t**3) * p[3]
                for _, p in enumerate(np.transpose(points))]

    except AssertionError as error:
        print('[ERROR] Insufficient number of entry points.')
        print('[ERROR] The correct number of entry points is %d.' % CONST_NUM_OF_ENTRY_POINTS_CUBIC)
        print('[ERROR] The number of samples must not be negative.')

class N_Degree(object):
    """
    Description:
        Class for efficient solution of N-degree Bézier curve.

        Note:
            A Bézier curve is a parametric curve used in computer graphics and related fields.

    Initialization of the Class:
        Input:
            (1) num_of_samples [INT]: Number of samples to generate. Must be non-negative.

        Example:
            Initialization:
                Cls = N_Degree(num_of_samples)
            Calculation:
                res = Cls.Solve(p, simplification_factor)

                where p is equal to [[px_id_0, py_id_0], .., [px_id_n, py_id_n]] in 2D space
                and [[px_id_0, py_id_0, pz_id_0], .., [px_id_n, py_id_n, pz_id_n]] in 3D space
    """

    def __init__(self, num_of_samples: typing.Union[int]) -> None:
        # << PUBLIC >> #
        try:
            assert(num_of_samples >= 0)

            # Return evenly spaced numbers over a specified interval.
            self.t = np.linspace(CONST_T_START, CONST_T_STOP, num_of_samples)

        except AssertionError as error:
            print('[ERROR] The number of samples must not be negative.')

        # << PRIVATE >> #
        # Points [Float Matrix]
        self.__points = []
        # Number of samples to generate
        self.__num_of_samples = num_of_samples

    @staticmethod
    def __path_simplification(points, simplification_factor):
        """
        Description:
            Function to simplify the path through the simplification factor. The first and end points do not change, the others
            depend on the factor coefficient.

            Example:
                Input Points:
                    points = [1.0, 1.0], [1.25, 2.0], [1.75, 2.0], [2.0, 1.0], [1.0, -1.0], [1.25, -2.0], [1.75, -2.0], [2.0, -1.0]
                Number of points:
                    n = 8
                Simplification Factor:
                    1\ Example:
                        simplification_factor = 1
                        points_new = [1.0, 1.0], [1.25, 2.0], [1.75, 2.0], [2.0, 1.0], [1.0, -1.0], [1.25, -2.0], [1.75, -2.0], [2.0, -1.0]
                        n = 8
                    2\ Example:
                        simplification_factor = 2
                        points_new = [1.0, 1.0], [None], [1.75, 2.0], [None], [1.0, -1.0], [None], [1.75, -2.0], [2.0, -1.0]
                        points_new = [1.0, 1.0], [1.75, 2.0], [1.0, -1.0], [1.75, -2.0], [2.0, -1.0]
                        n = 5
        Args:
            (1) points [p_{0, .., n}] [Int/Float Matrix]: Multiple points to create a curve.
            (2) simplification_factor [INT]: Simplification factor for the simplify the path.

        Returns:
            (1) parameter [Int/Float Matrix]: New simplified matrix of points to create a curve.

        """

        points_aux = []
        points_aux.append(points[0])

        for i in range(1, len(points) - 1):
            if i % simplification_factor == 0:
                points_aux.append(points[i])

        if points_aux[-1] != points[-1]:
            points_aux.append(points[-1])

        return points_aux

    @staticmethod
    def __binomial_coefficient(n, k):
        """
        Description:
            Calculation binomial coofecient C, from pair of integers n ≥ k ≥ 0 and is written (n k). The binomial coefficients are the positive integers that occur as coefficients in the binomial theorem.

            (n k) = n! / (k! * (n - k)!)
            ...
            Simplification of the calculation:
            (n k) = ((n - k + 1) * (n - k + 2) * ... * (n - 1) * (n)) / (1 * 2 * ... * (k - 1) * k)

        Args:
            (1) n [INT]: Integer number 1 (numerator)
            (2) k [INT]: Integer number 2 (denumerator)

        Returns:
            (1) parameter [INT]: Binomial coofecient C(n k).
        """
        try:
            assert(n >= k)

            if k == 0:
                return 1
            elif k == 1:
                return n
            else:
                c_nk = 1

                # Calculation from the simplification equation
                for i in range(0, k):
                    c_nk *= (n - i) # numerator
                    c_nk /= (i + 1) # denumerator

                return c_nk

        except AssertionError as error:
            print('[ERROR] The number n must be larger than or equal to k.')
            return 0

    def __n_index_curve(self, i, point, n, c_ni):
        """
        Description:
            Given n + 1 control points p_{0}, p_{1},..., p_{n} we define the degree n Bezier curve to
            be the curve parametrized by (De Casteljau's algorithm):

            p(t) = sum(i = 0 -> n) (C(n i)) * (t ^ i) * ((1 - t) ^ (n - i)) * p_{i}, t ∈ [0, 1]

            where C(n i) is a binomial coefficient.

        Args:
            (1) i [INT]: Iteration.
            (2) point [Int/Float Matrix]: Point (2D/3D) in interation (i).
            (3) n [INT]: Number of points.
            (4) c_ni [INT]: Binomial coofecient C(n i) in iteration (i).

        Returns:
            (1) parameter [Int/Float Matrix]: Results of curve values in iteration (i).
        """

        return [c_ni * (self.t**i) * ((1 - self.t)**(n - i)) * p
                for _, p in enumerate(point)]

    def __n_degree(self):
        """
        Description:
            The main control function for creating a Bézier curve of degree n.

        Returns:
            (1) parameter [{0 .. Number of dimensions - 1}] [Int/Float Matrix]: Resulting points of the curve.
        """

        # Number of points in the matrix
        n = len(self.__points) - 1

        # Calculation of binomial cooficient of the first iteration
        c_nk = self.__binomial_coefficient(n, 0)
        # Calculation of the first curve positions
        result = self.__n_index_curve(0, self.__points[0], n, c_nk)

        for i in range(1, n + 1):
            # Binomial cooficient in interation (i)
            c_ni = self.__binomial_coefficient(n, i)

            # Calculation positions in iteration (i)
            aux_result = self.__n_index_curve(i, self.__points[i], n, c_ni)

            # The sum of all positions for the resulting Bézier curve
            for j in range(0, len(aux_result)):
                result[j] += aux_result[j]

        return result

    def Solve(self, points: typing.Union[typing.List[int], typing.List[float]], simplification_factor: typing.Union[int]) -> typing.Union[typing.List[int], typing.List[float]]:
        """
        Description:
            Function for automatic calculation of a suitably selected Bézier curve.

        Args:
            (1) points [p_{0, .., n}] [Int/Float Matrix]: Multiple points to create a curve.
            (2) simplification_factor [INT]: Simplification factor for the simplify the path.

        Return:
            (1) parameter [Int/Float Matrix]: Resulting points of the curve.
        """

        try:
            assert len(points) > 1

            # If the number of input points is greater than 4 and variable simplification_factor > 1, the program chooses the n_points calculation method. But if the simplification
            # coefficient is greater than or equal to 1, the program can choose another method and the principle of calculation will be faster.
            if simplification_factor > 1 and len(points) > 4:
                # If the coefficient coefficient is greater than 1, simplify the path
                self.__points = self.__path_simplification(points, simplification_factor)
            else:
                self.__points = points

            # Selects the calculation method based on the number of points in the matrix (p).
            if len(self.__points) > 4:
                return self.__n_degree()
            if len(self.__points) == 4:
                return Cubic(self.__num_of_samples, self.__points)
            elif len(self.__points) == 3:
                return Quadratic(self.__num_of_samples, self.__points)
            elif len(self.__points) == 2:
                return Linear(self.__num_of_samples, self.__points)

        except AssertionError as error:
            print('[ERROR] Insufficient number of entry points.')
            print('[ERROR] The minimum number of entry points is %d.' % CONST_NUM_OF_ENTRY_POINTS_LINEAR)


import matplotlib.pyplot as plt
import numpy as np
class EulerNumericalSolution():
    def __init__(self, type, val, f, t_min, t_max, x_init):
        if type == "h":
            self.h = val
            self.n = int((t_max-t_min)/ self.h)
        elif type == "N":
            self.n = val
            self.h = (t_max - t_min) / self.n
        self.t_min = t_min
        self.t_max = t_max
        self.x_init = x_init
        self.f = f

    def simulate(self):
        ts, xs = [self.t_min], [self.x_init]
        cur_t = self.t_min
        cur_x = self.x_init

        for iteration in range(self.n):
            cur_x += self.f(cur_x, cur_t) * self.h
            cur_t += self.h
            ts.append(cur_t)
            xs.append(cur_x)

        return ts, xs

    def plot(self, legend):
        ts, xs = self.simulate()
        plt.plot(ts, xs, label=legend)
        plt.title("Comparison result")
        plt.xlabel("t")
        plt.ylabel("x")
        plt.grid()
        #plt.show()


#!/usr/bin/env python3

import numpy as np

#################################################
### Functions Definitions
#################################################

def heat_source(t, x, N, letter):
    """
    Calcula o valor da fonte de calor de um determinado problema,
    em um determinado instante, em uma determinada posição.
    """

    if letter == "a":
        result = 10 * np.cos(10 * t) * (x**2) * ((1 - x)**2) - (1 + np.sin(10 * t)) * (12 * (x**2) - 12 * x + 2)
    elif letter == "b":
        result = 5 * np.exp(t - x) * ((5 * (t**2) * np.cos(5 * t * x)) - (np.sin(5 * t * x) * (2 * t + x)))
    elif letter == "c":
        r = 10000 * (1 - 2 * (t**2))

        h = 1 / N
        p = 0.25

        if (p - h / 2) <= x <= (p + h / 2):
            gh = N
        else:
            gh = 0

        result = r * gh
    else:
        result = 0

    return result

def u_solution(t, x, letter):
    """
    Calcula o valor da solução de um determinado problema,
    em um determinado instante, em uma determinada posição.
    """

    if letter == "a":
        result = (1 + np.sin(10 * t)) * (x**2) * ((1 - x)**2)
    elif letter == "b":
        result = np.exp(t - x) * np.cos(5 * t * x)
    elif letter == "c":
        result = 0
    else:
        result = 0

    return result

def initial_condition(x, letter):
    """
    Retorna as condições iniciais de u determinado problema em
    uma determinada posição.
    """

    if letter == "a":
        result = (x**2) * ((1 - x)**2)
    elif letter == "b":
        # result = u_solution(0, x, letter)
        result = np.exp(-x)
    elif letter == "c":
        result = 0
    else:
        result = 0

    return result

def boundary_conditions(t, letter):
    """
    Retorna as condições de contorno de um determinado problema,
    em um determinado instante.

    Se retorna primeiro a condição de contorno em x = 0, depois
    em x = 1.
    """

    if letter == "a":
        cond_zero = 0
        cond_one = 0
    elif letter == "b":
        # cond_zero = u_solution(t, 0, letter)
        cond_zero = np.exp(t)
        # cond_one = u_solution(t, 1, letter)
        cond_one = np.exp(t - 1) * np.cos(5 * t)
    elif letter == "c":
        cond_zero = 0
        cond_one = 0
    else:
        cond_zero = 0
        cond_one = 0

    return cond_zero, cond_one

def create_u(times_array, positions_array, letter):
    """
    Cria uma matrix U, dado um vetor com a discretização do tempo
    e um vetor com a descretização do espaço.

    A matriz é inicializada com as condições de contorno e condições
    iniciais, dependendo do problema que se está analizando.
    """

    num_of_times = len(times_array)
    num_of_position = len(positions_array)

    # Create U matrix
    U = np.zeros((num_of_times, num_of_position))

    # Initial conditions calculation
    for i in range(0, num_of_position):
        U[0][i] = initial_condition(positions_array[i], letter)

    # Boundary conditions calculation
    for k in range(0, num_of_times):
        U[k][0], U[k][-1] = boundary_conditions(times_array[k], letter)

    return U


""" File containing PCA class """
import numpy as np
import matplotlib.pyplot as plt

class PCA:
    """ Performs Primary Component Analysis """
    def __init__(self, filename):
        """ Loads csv to array """
        self.col = 0
        self.dimensions = 0     # D in the assignment
        if filename == 'swiss_data.csv':
            self.col = 2000
            self.dimensions = 3
            self.choice = 0
        elif filename == 'digits.csv':
            self.col = 5620
            self.dimensions = 64
            self.choice = 1
            self.labels = np.genfromtxt('../csv/digits_label.csv', delimiter=',').tolist()

        if self.col == 0 and self.dimensions == 0:
            print("wrong filename")
        else:
            raw_data = np.genfromtxt('../csv/' + filename, delimiter=',')   # X
            self.small_x = np.reshape(raw_data, (self.col, self.dimensions))
            self.fit = 0    # F in the assignment

    def fit_data(self):
        """ Creates fit using PCA and assigns it to self.F """
        self.small_x = self.small_x - np.mean(self.small_x, axis=0)
        covmatrix = np.cov(self.small_x.T)

        [eigenvalues, eigenvectors] = np.linalg.eig(covmatrix)

        eig_pairs = [(np.abs(eigenvalues[i]), eigenvectors[:, i]) for i in range(len(eigenvalues))]
        eig_pairs.sort(key=lambda x: x[0], reverse=True)
        self.fit = np.hstack((eig_pairs[0][1].reshape(self.dimensions, 1),
                              eig_pairs[1][1].reshape(self.dimensions, 1)))

    def transform(self):
        """ Transforms data using fit (self.fit). Plots result. """
        small_y = self.fit.T @ (self.small_x.T)
        if self.choice == 0 :
            plt.scatter(small_y[1, :], small_y[0, :],
                        c=np.arange(self.col), cmap='gist_rainbow', s=7)
        elif self.choice == 1:
            plt.scatter(small_y[0, :], small_y[1, :],
                        c=self.labels, cmap='jet', s=7, marker=".")
        plt.show()


# -*- coding: utf-8 -*-
"""Principal Component Analysis

Created on Tue Sep 29 20:11:23 2009
Author: josef-pktd

TODO : add class for better reuse of results
"""

import numpy as np

def pca(data, keepdim=0, normalize=0, demean=True):
    '''principal components with eigenvector decomposition
    similar to princomp in matlab

    Parameters
    ----------
    data : ndarray, 2d
        data with observations by rows and variables in columns
    keepdim : integer
        number of eigenvectors to keep
        if keepdim is zero, then all eigenvectors are included
    normalize : boolean
        if true, then eigenvectors are normalized by sqrt of eigenvalues
    demean : boolean
        if true, then the column mean is subtracted from the data

    Returns
    -------
    xreduced : ndarray, 2d, (nobs, nvars)
        projection of the data x on the kept eigenvectors
    factors : ndarray, 2d, (nobs, nfactors)
        factor matrix, given by np.dot(x, evecs)
    evals : ndarray, 2d, (nobs, nfactors)
        eigenvalues
    evecs : ndarray, 2d, (nobs, nfactors)
        eigenvectors, normalized if normalize is true

    Notes
    -----

    See Also
    --------
    pcasvd : principal component analysis using svd

    '''
    x = np.array(data)
    #make copy so original doesn't change, maybe not necessary anymore
    if demean:
        m = x.mean(0)
    else:
        m = np.zeros(x.shape[1])
    x -= m

    # Covariance matrix
    xcov = np.cov(x, rowvar=0)

    # Compute eigenvalues and sort into descending order
    evals, evecs = np.linalg.eig(xcov)
    indices = np.argsort(evals)
    indices = indices[::-1]
    evecs = evecs[:,indices]
    evals = evals[indices]

    if keepdim > 0 and keepdim < x.shape[1]:
        evecs = evecs[:,:keepdim]
        evals = evals[:keepdim]

    if normalize:
        #for i in range(shape(evecs)[1]):
        #    evecs[:,i] / linalg.norm(evecs[:,i]) * sqrt(evals[i])
        evecs = evecs/np.sqrt(evals) #np.sqrt(np.dot(evecs.T, evecs) * evals)

    # get factor matrix
    #x = np.dot(evecs.T, x.T)
    factors = np.dot(x, evecs)
    # get original data from reduced number of components
    #xreduced = np.dot(evecs.T, factors) + m
    #print x.shape, factors.shape, evecs.shape, m.shape
    xreduced = np.dot(factors, evecs.T) + m
    return xreduced, factors, evals, evecs

def pcasvd(data, keepdim=0, demean=True):
    '''principal components with svd

    Parameters
    ----------
    data : ndarray, 2d
        data with observations by rows and variables in columns
    keepdim : integer
        number of eigenvectors to keep
        if keepdim is zero, then all eigenvectors are included
    demean : boolean
        if true, then the column mean is subtracted from the data

    Returns
    -------
    xreduced : ndarray, 2d, (nobs, nvars)
        projection of the data x on the kept eigenvectors
    factors : ndarray, 2d, (nobs, nfactors)
        factor matrix, given by np.dot(x, evecs)
    evals : ndarray, 2d, (nobs, nfactors)
        eigenvalues
    evecs : ndarray, 2d, (nobs, nfactors)
        eigenvectors, normalized if normalize is true

    See Also
    -------
    pca : principal component analysis using eigenvector decomposition

    Notes
    -----
    This doesn't have yet the normalize option of pca.

    '''
    nobs, nvars = data.shape
    #print nobs, nvars, keepdim
    x = np.array(data)
    #make copy so original doesn't change
    if demean:
        m = x.mean(0)
    else:
        m = 0
##    if keepdim == 0:
##        keepdim = nvars
##        "print reassigning keepdim to max", keepdim
    x -= m
    U, s, v = np.linalg.svd(x.T, full_matrices=1)
    factors = np.dot(U.T, x.T).T #princomps
    if keepdim:
        xreduced = np.dot(factors[:,:keepdim], U[:,:keepdim].T) + m
    else:
        xreduced = data
        keepdim = nvars
        "print reassigning keepdim to max", keepdim

    # s = evals, U = evecs
    # no idea why denominator for s is with minus 1
    evals = s**2/(x.shape[0]-1)
    #print keepdim
    return xreduced, factors[:,:keepdim], evals[:keepdim], U[:,:keepdim] #, v

__all__ = ['pca', 'pcasvd']


# Question: https://projecteuler.net/problem=588

# https://oeis.org/A247649

"""
    Let f(x) = x^4 + x^3 + x^2 + x + 1
    Then Q(N) = (f(x) ** N) (mod 2)
    Some notes:
        * We can do polynomial multiplication via np.convolve, as np.convolve(a,v,'full') is essentially
    polynomial multiplication.
        * Using a method similar to "exponentiation by squaring" (https://en.wikipedia.org/wiki/Modular_exponentiation#Right-to-left_binary_method), we can calculate Q(N) in O(log(N)) rather than in O(N).
        * From the FORMULA section in https://oeis.org/A247649, we can quickly find Q(n) as followed,
            + In the binary form of n, split the binary form by '00'. For example, split('01100010') = ('11', '10').
            + Let (a_1, a_2, ..., a_m) be the splitted form, then
                Q(N) = Q(a_1) * Q(a_2) * ... * Q(a_m)
            + For n that couldn't be furtherly splitted into more than 1 element, we have to manually calculate Q(n).
            + Using the relation, we "only" need to use polynomial multiplication to calculate Q(n) of n upto around 27000.
"""

import numpy as np

N = 18

def Q_brute_force(n):
    f = np.array([1])
    g = np.array([1,1,1,1,1])
    while n > 0:
        bit = n % 2
        if bit == 1:
            f = np.convolve(f, g)
        g = np.convolve(g, g)
        n //= 2
    return np.sum(f%2)

""" # This is also correct
def Q_brute_force(n):
    f = np.array([1,1,1,1,1])
    g = np.array([1,1,1,1,1])
    for _ in range(n-1):
        f = np.convolve(f, g)
    return np.sum(f%2)
"""

def Q(n, cache):
    binary_form_n = bin(n)[2:]
    parts = binary_form_n.split('00')
    ans = 1
    if len(parts) == 1:
        return Q_brute_force(int(parts[0], 2))
    for part in parts:
        if not part:
            continue
        next_n = int(part, 2)
        if not next_n in cache:
            cache[next_n] = Q(next_n, cache)
        ans *= cache[next_n]
    return ans

if __name__ == "__main__":
    ans = 0
    cache = {0:1, 1:5}
    for exp in range(1, N+1):
        n = 10**exp
        ans += Q(n, cache)
    print(ans)


# Figure 20.6, 20.7, 20.8

# PCA train set and test set reconstruction error vs K
# Reconstruction error on test set gets lower as K increased
# Screeplot and fraction of variance explained
# likelihood of PCA model shows “knee” or “elbow” in the curve

import superimport

import matplotlib.pyplot as plt
import numpy as np
from sklearn.decomposition import PCA
from scipy.stats import multivariate_normal
from tensorflow import keras
import warnings
from sklearn.metrics import mean_squared_error

warnings.simplefilter('ignore', RuntimeWarning) #for some NaN values

# Function to calculate log likelihood of PCA from eigenvalues
# Implemented equations from the book:
# "Probabilistic Machine Learning: An Introduction"

def log_likelihood(evals):

  Lmax = len(evals)
  ll = np.arange(0.0,Lmax)

  for L in range(Lmax):

    group1 = evals[0:L+1] #Divide Eigenvalues in two groups
    group2 = evals[L+1:Lmax]

    mu1 = np.mean(group1)
    mu2 = np.mean(group2)

    # eqn (20.30)
    sigma = (np.sum((group1-mu1)**2 ) + np.sum((group2-mu2)**2)) / Lmax

    ll_group1 = np.sum(multivariate_normal.logpdf(group1, mu1, sigma))
    ll_group2 = np.sum(multivariate_normal.logpdf(group2, mu2, sigma))

    ll[L] = ll_group1 + ll_group2 #eqn (20.31)

  return ll

# Standard mnist dataset

mnist = keras.datasets.mnist
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
train_images = train_images[train_labels == 3] # select images of digit '3'

n_images = 1000
train_images = train_images[0:n_images,:,:]
n_samples, n_rows, n_cols = train_images.shape
X = np.reshape(train_images, (n_samples, n_rows*n_cols))

X_train = X[0:int(n_images/2),:] #500 images in train set
X_test = X[int(n_images/2): ,:] #500 images in test set

#Reconstruction error on MNIST vs number of latent dimensions used by PCA

X_rank = np.linalg.matrix_rank(X_train)
K_linspace = np.linspace(1, 0.75*X_rank, 10, dtype=int)
Ks = np.unique(np.append([1, 5, 10, 20], K_linspace))

RMSE_train= np.arange(len(Ks))
RMSE_test = np.arange(len(Ks))

for index,K in enumerate(Ks):
   pca = PCA(n_components = K)

   Xtrain_transformed = pca.fit_transform(X_train)
   Xtrain_proj = pca.inverse_transform(Xtrain_transformed)
   RMSE_train[index] = mean_squared_error(X_train, Xtrain_proj, squared=False)

   Xtest_transformed = pca.transform(X_test)
   Xtest_proj = pca.inverse_transform(Xtest_transformed)
   RMSE_test[index] = mean_squared_error(X_test, Xtest_proj, squared=False)

#profile log likelihood for PCA

n_samples, n_features = X_train.shape
Kmax = min(n_samples, n_features)

pca = PCA(n_components = Kmax)
X_transformed = pca.fit_transform(X_train)
evals = pca.explained_variance_ #eigenvalues in descending order

ll = log_likelihood(evals)

#Fraction of variance explained

fraction_var = np.cumsum(evals[0:50]/np.sum(evals))

#Figure 20.6(a) train set reconstruction error

fig, ax = plt.subplots()
xs = Ks
ys = RMSE_train
plt.title('train set reconstruction error')
plt.xlabel('num PCs')
plt.ylabel('rmse')
ax.plot(xs, ys, marker = 'o')
plt.show()

#Figure 20.6(b) test set reconstruction error

fig, ax = plt.subplots()
xs = Ks
ys = RMSE_test
plt.title('test set reconstruction error')
plt.xlabel('num PCs')
plt.ylabel('rmse')
ax.plot(xs, ys, marker = 'o')
plt.show()

#Figure 20.7(a) Scree plot for training set

fig, ax = plt.subplots()
xs = np.arange(1, 51)
ys = evals[0:50]
plt.title('screeplot')
plt.xlabel('num PCs')
plt.ylabel('eigenvalues')
plt.ticklabel_format(axis="y", style="sci", scilimits=(0,0))
ax.plot(xs, ys)
plt.show()

#Figure 20.7(b) Fraction of variance explained

fig, ax = plt.subplots()
xs = np.arange(1, 51)
ys = fraction_var
plt.xlabel('num PCs')
plt.ylabel('proportion of variance explained')
ax.plot(xs, ys)
plt.show()

#Figure 20.8 Profile likelihood corresponding to PCA model

fig, ax = plt.subplots()
xs = np.arange(1, 51)
ys = ll[0:50]
plt.xlabel('num PCs')
plt.ylabel('profile log likelihood')

ax.plot(xs, ys)
plt.show()


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

def create_plotting_parameters_for_normal_distribution(mean, variance, num_std_dev_to_plot=3):
    """Create parameters to easily plot a normal distribution

    Arguments:
        mean {float} -- Mean of the normal distribution
        variance {float} -- Variance of the normal distribution

    """
    sigma = sqrt(variance)
    # I set the default range of x to be plus or minus 3 sigma since that has
    # the important visual part of the normal distribution
    x = np.linspace(mean - num_std_dev_to_plot*sigma,
                    mean + num_std_dev_to_plot*sigma, 100)
    y = stats.norm.pdf(x, mean, sigma)
    return x, y

if __name__ == "__main__":
    x, y = create_plotting_parameters_for_normal_distribution(0, 3)
    plt.plot(x, y)
    plt.show()


"""
Implementation of the bigClAM algorithm.
Throughout the code, we will use tho following variables
  * F refers to the membership preference matrix. It's in [NUM_PERSONS, NUM_COMMUNITIES]
   so index (p,c) indicates the preference of person p for algorithms c.
  * A refers to the adjency matrix, also named friend matrix or edge set. It's in [NUM_PERSONS, NUM_PERSONS]
    so index (i,j) indicates is 1 when person i and person j are friends.
"""

import numpy as np
import networkx as nx

def sigm(x):
    return np.divide(np.exp(-1.0 * x), 1.0 - np.exp(-1.0 * x))

def log_likelihood(F, A):
    """implements equation 2 of
    https://cs.stanford.edu/people/jure/pubs/bigclam-wsdm13.pdf"""
    A_soft = F.dot(F.T)

    # Next two lines are multiplied with the adjacency matrix, A
    # A is a {0,1} matrix, so we zero out all elements not contributing to the sum
    FIRST_PART = A * np.log(1.0 - np.exp(-1.0 * A_soft))
    sum_edges = np.sum(FIRST_PART)
    SECOND_PART = (1 - A) * A_soft
    sum_nedges = np.sum(SECOND_PART)

    log_likeli = sum_edges - sum_nedges
    return log_likeli

def gradient(F, A, i):
    """Implements equation 3 of
    https://cs.stanford.edu/people/jure/pubs/bigclam-wsdm13.pdf

      * i indicates the row under consideration

    The many forloops in this function can be optimized, but for
    educational purposes we write them out clearly
    """
    N, C = F.shape
    neighbours = np.where(A[i])
    nneighbours = np.where(1 - A[i])

    sum_neigh = np.zeros((C,))
    for nb in neighbours[0]:
        dotproduct = F[nb].dot(F[i])
        sum_neigh += F[nb] * sigm(dotproduct)

    sum_nneigh = np.zeros((C,))
    # Speed up this computation using eq.4
    for nnb in nneighbours[0]:
        sum_nneigh += F[nnb]

    grad = sum_neigh - sum_nneigh
    return grad

def train(A, C, iterations=100):
    # initialize an F
    N = A.shape[0]
    F = np.random.rand(N, C)

    for n in range(iterations):
        for person in range(N):
            grad = gradient(F, A, person)

            F[person] += 0.005 * grad

            F[person] = np.maximum(0.001, F[person])  # F should be nonnegative
        log_likelihood(F, A)
    return F

def big_Clam(graph, number_communities):
    adj = nx.to_numpy_matrix(graph)
    F = train(adj, number_communities)
    F_argmax = np.argmax(F, 1)
    dict_communities = {}
    for i in range(0, number_communities):
        dict_communities[i] = []
    for node, com in zip(graph.nodes(), F_argmax):
        dict_communities[com].append(node)

    list_communities = []
    for com in dict_communities:
        list_communities.append(dict_communities[com])

    return list_communities


import numpy as np

def dydx(x, y):
    return 2*x + np.sin( x * y )

x0 = float(input("Enter value of x0:- "))
y0 = float(input("Enter value oy y0:- "))
h = float(input("Enter step size:- "))
n = int(input("Enter number of points."))

y_vec = np.zeros((n, 1))
y_vec[0] = y0
x_vec = np.zeros((n, 1))
x_vec[0] = x0
for i in range(n-1):
    xi, yi = x_vec[i], y_vec[i]
    k1 = dydx(xi, yi)
    k2 = dydx(xi + h/2, yi + h*k1/2)
    k3 = dydx(xi + h/2, yi + h*k2/2)
    k4 = dydx(xi + h, yi + k3)
    x_vec[i+1] = xi + h
    y_vec[i+1] = yi + h / 6 * (k1 + 2*k2 + 2*k3 + k4)

print("--- Results ---")
print("x    |   y")
print(np.array([x_vec, y_vec]).T)


#!/usr/bin/env python

if __name__ == '__main__':

    from argparse import ArgumentParser
    from math import exp
    import numpy as np

    min_val = -1.0
    max_val = 1.0
    default_points = 10
    default_a = 1.0
    arg_parser = ArgumentParser(description='produce a 3D scalar field')
    arg_parser.add_argument('-x', type=int, default=default_points,
                            help='number of x points')
    arg_parser.add_argument('-y', type=int, default=default_points,
                            help='number of y points')
    arg_parser.add_argument('-z', type=int, default=default_points,
                            help='number of z points')
    arg_parser.add_argument('-a_x', type=float, default=default_a,
                            help='alpha_x')
    arg_parser.add_argument('-a_y', type=float, default=default_a,
                            help='alpha_y')
    arg_parser.add_argument('-a_z', type=float, default=default_a,
                            help='alpha_z')
    options = arg_parser.parse_args()
    print 'x,y,z,value'
    for x in np.linspace(min_val, max_val, num=options.x, endpoint=True):
        for y in np.linspace(min_val, max_val, num=options.y, endpoint=True):
            for z in np.linspace(min_val, max_val, num=options.z, endpoint=True):
                val = exp(-(options.a_x*x**2 +
                            options.a_y*y**2 +
                            options.a_z*z**2))
                print '{x:.4f},{y:.4f},{z:.4f},{val:.8f}'.format(x=x,
                                                                 y=y,
                                                                 z=z,
                                                                 val=val)


from os import name
import numpy as np

def golden_section_search(fun, eps=1e-5, interval=None):
    if interval is None:
        print('暂时不处理这一功能')
        return
    key = (np.sqrt(5)-1)/2
    len_interval = interval[1]-interval[0]
    right = interval[0]+key*len_interval
    left = interval[1]-key*len_interval
    while len_interval > eps:
        len_interval *= key
        if fun(left) <= fun(right):
            interval[1] = right
            right = left
            left = interval[1]-key*len_interval
        else:
            interval[0] = left
            left = right
            right = interval[0]+key*len_interval
        print(interval)
    return (interval[1]+interval[0])/2

if __name__ == '__main__':
    def foo(x): return 1-x*np.exp(-x**2)
    print('0.618法', golden_section_search(
        foo, 0.01, interval=[0, 1]), '解析解', np.sqrt(0.5))


import numpy as np

#Tricycle Robot Model
#Input:
#Input Vehicle parameters:
#r = radius of the front wheel
#d = distance between the front wheel and the two back wheels
#L = distance between the two back wheels (not relevant for the model's behavior, but it might be for visualization purposes)
#Control Input parameters:
#u = front wheel angular velocity
#alpha = steering angle of the front wheel
#Robot State Input parameters
#(x,y) = initial robot position in 2D, measured at the center between the two back wheels
#theta = initial robot orientation, angle counterclockwise from the x-axis

#Output: New robot state
#(x,y) = position in 2D
#theta = angle with respect to the x-axis

#The following input parameters should be reflected in the visualization of the robot model:
#r, alpha, d

#this method is the same for all robot models
def forwardKinematics(R, omega, ICC, x, y, theta, t):
    x_new = (np.cos(omega * t) * (x - ICC[0])) + (-np.sin(omega * t) * (y - ICC[1])) + ICC[0]
    y_new = (np.sin(omega * t) * (x - ICC[0])) + (np.cos(omega * t) * (y - ICC[1])) + ICC[1]
    theta_new = theta + (omega * t)
    return [x_new, y_new, theta_new]

#this method is the same for all robot models
def straightMotion(v, x, y, theta, t):
    x_new = x + (v * t * np.cos(theta))
    y_new = y + (v * t * np.sin(theta))
    theta_new = theta
    return [x_new, y_new, theta_new]

#this is the only part that's different from the differential drive model
def robotStep(r, d, u, alpha, x, y, theta, t):
    v = u * r                                 #linear velocity of the front wheel

    if alpha == 0:                            #driving straight
        [x,y,theta] = straightMotion(v, x, y, theta, t)
    else:
        R = d * np.tan((np.pi/2) - alpha)
        omega = v/np.sqrt(d**2 + R**2)
        ICC = [x - R * np.sin(theta), y + R * np.cos(theta)] #Instantaneous Center of Curvature

        [x,y,theta] = forwardKinematics(R, omega, ICC, x,y, theta, t)

    return [x,y,theta]

def main(x, y, r, d, u, alpha, theta):

    robot_path = []

    t = 0
    t_step = 0.1                                       #update rate for the visualization

    #read all the input parameters described above from the user interface

    robot_path.append((x,y))

    #main loop
    loopy = 0

    while(loopy < 100):
        t = t+t_step
        [x, y , theta] = robotStep(r, d, u, alpha, x, y, theta, t_step)
        robot_path.append((x,y))
        loopy += 1;

    print(robot_path)