"""
    Mamy dwie macierze Am×n i Bn×k. Należy napisać funkcję obliczającą ich iloczyn.

    1) Za pomocą iteracji po elementach (potrójna pętla).
    2) Korzystając z faktu, że każdy element macierzy  Cij jest
       iloczynem skalarnym  i-tego rzędu macierzy A oraz
       j-tego rzędu macierzy B (podwójna pętla)
    3) Używając funkcji:  np.dot lub np.tensordot (bez pętli)
"""

import numpy as np

MESSAGE_REGARDING_DIFFERENT_DIMENSIONS = 'The number of columns ' \
                                         'in the first matrix ' \
                                         'should be the same as ' \
                                         'the number of rows in the second matrix.'

def C1(A, B):

    # Wymiary m, n, k

    # m - liczka wierszy macierzy A
    # n - liczba kolumn macierzy A, liczba wierszy macierzy B
    # k - liczba kolumn macierzy B

    m, n_1 = A.shape
    n_2, k = B.shape

    # Jeżeli liczba kolumn macierzy A jest różna od liczby wierszy macierzy B
    # wyrzuć wyjątek
    if n_1 != n_2:
        raise ValueError(MESSAGE_REGARDING_DIFFERENT_DIMENSIONS)

    # Macierz C będzie miał wymiary (m,k)
    C = np.zeros((m, k))

    for i in range(m):

        for j in range(k):

            # Element Cij to iloczyn skalarny i-tego wiersza macierzy A i j-tej kolumny macierzy B

            scalar_product = 0

            # Zarówno każdy wiersz macierzy A jak i każda kolumna macierzy B zawiera n elementów
            for l in range(n_1):
                scalar_product += A[i][l] * B.T[j][l]

            C[i][j] = scalar_product

    return C

def C2(A, B):

    # Wymiary m, n, k

    # m - liczka wierszy macierzy A
    # n - liczba kolumn macierzy A, liczba wierszy macierzy B
    # k - liczba kolumn macierzy B

    m, n_1 = A.shape
    n_2, k = B.shape

    # Jeżeli liczba kolumn macierzy A jest różna od liczby wierszy macierzy B
    # wyrzuć wyjątek
    if n_1 != n_2:
        raise ValueError(MESSAGE_REGARDING_DIFFERENT_DIMENSIONS)

    # Macierz C będzie miał wymiary (m,k)
    C = np.zeros((m, k))

    for i in range(m):

        for j in range(k):
            # Element Cij to iloczyn skalarny i-tego wiersza macierzy A i j-tej kolumny macierzy B
            # aby go obliczyć używamy funkcji wbudowanej inner
            scalar_product = np.inner(A[i], B.T[j])
            C[i][j] = scalar_product

    return C

def C3(A, B):

    # n - liczba kolumn macierzy A, liczba wierszy macierzy B
    n_1 = A.shape[1]
    n_2 = B.shape[0]

    # Jeżeli liczba kolumn macierzy A jest różna od liczby wierszy macierzy B
    # wyrzuć wyjątek
    if n_1 != n_2:
        raise ValueError(MESSAGE_REGARDING_DIFFERENT_DIMENSIONS)

    C = np.dot(A, B)
    return C

# Tests
m = np.arange(9).reshape(3,3)
assert np.prod(C1(np.eye(3),m) == m)
assert np.prod(C1(m,m) == C3(m,m))
assert np.prod(C2(m,m) == C3(m,m))

try:
    C1(np.arange(9).reshape(3,3),np.ones((2,3)))
except (BaseException, Exception) as error:
    if type(error) != ValueError or \
            str(error) != MESSAGE_REGARDING_DIFFERENT_DIMENSIONS:
        raise AssertionError("Second dimension of matrix "
                             "should be the same as dimension of vector!.")

try:
    C2(np.arange(9).reshape(3,3),np.ones((2,3)))
except (BaseException, Exception) as error:
    if type(error) != ValueError or \
            str(error) != MESSAGE_REGARDING_DIFFERENT_DIMENSIONS:
        raise AssertionError("Second dimension of matrix "
                             "should be the same as dimension of vector!.")

try:
    C3(np.arange(9).reshape(3, 3), np.ones((2, 3)))
except (BaseException, Exception) as error:
    if type(error) != ValueError or \
            str(error) != MESSAGE_REGARDING_DIFFERENT_DIMENSIONS:
        raise AssertionError("Second dimension of matrix "
                             "should be the same as dimension of vector!.")

print("All tests were successful.")


"""Principal Component Analysis."""

import numpy as np

from typing import Optional

from alchina.exceptions import InvalidInput, NotFitted
from alchina.utils import features_reshape

class PCA(object):
    """Principal Component Analysis algorithm."""

    def __init__(self, n_components: Optional[int] = None):
        self.n_components = n_components

        self._covariance_matrix = None
        self._U_reduced = None
        self._mean = None

    def fit(self, X):
        """Train the model."""
        X = features_reshape(X)
        max_dimension = min(X.shape)

        if self.n_components is None:
            self.n_components = max_dimension
        elif self.n_components > max_dimension:
            raise InvalidInput(f"n_components must be lesser than {max_dimension}")

        self._covariance_matrix = np.cov(X.T)
        self._mean = np.mean(X, axis=0)

        U, _, _ = np.linalg.svd(self._covariance_matrix)
        self._U_reduced = U[:, : self.n_components]

    def transform(self, X):
        """Transform the input."""
        if self._U_reduced is None or self._mean is None:
            raise NotFitted("the model must be fitted before usage")

        return (X - self._mean).dot(self._U_reduced)

    def fit_transform(self, X):
        """Fit the model and transform the input."""
        self.fit(X)
        return self.transform(X)

    def score_samples(self, X):
        """Compute the log-likelihood of all samples."""
        if self._U_reduced is None or self._mean is None:
            raise NotFitted("the model must be fitted before usage")

        X = features_reshape(X)

        n_features = X.shape[1]
        precision = np.linalg.inv(self._covariance_matrix)
        residuals = X - self._mean

        return -(1 / 2) * (
            -np.log(np.linalg.det(precision))
            + np.sum((residuals * np.dot(residuals, precision)), axis=1)
            + n_features * np.log(2 * np.pi)
        )

    def score(self, X):
        """Compute the mean of log-likelihood of all samples."""
        return np.mean(self.score_samples(X))


'''
One-versus-all regularised logistic regression

Bence Mélykúti
23/02/2018
'''

import numpy as np
import csv
import itertools
import matplotlib.pyplot as plt
from sklearn import linear_model
from sklearn.preprocessing import PolynomialFeatures
import scipy.io # to open Matlab's .mat files
import time

# own implementation, not really recommended or necessary:
def reglogreg_manual(X, y, num_labels, lambda0):
#    all_theta = np.zeros((num_labels, 1+X.shape[1]))
    data_prediction = np.zeros((X.shape[0], num_labels))

    for i in range(num_labels):
        lreg = linear_model.LogisticRegression(C=1/lambda0, fit_intercept=True, intercept_scaling=100)
        y_i = np.zeros_like(y)
        y_i[y==i] = 1
        y_i[y!=i] = 0

        lreg.fit(X, y_i) # there is no first column with all 1s, but it is taken care of by fit_intercept=True
#        all_theta[i, 0] = lreg.intercept_
#        all_theta[i, 1:] = np.ravel(lreg.coef_)

        data_prediction[:,i] = np.ravel(lreg.predict_proba(X)[:,1])

    pred = np.argmax(data_prediction, axis=1)
    return pred, data_prediction#, all_theta

# built-in version; benchmarking shows that it's not much faster
def reglogreg(X, y, lambda0):
    lreg = linear_model.LogisticRegression(C=1/lambda0, fit_intercept=True, intercept_scaling=100, multi_class='ovr') # ovr = one-vs-rest
    lreg.fit(X,y)
    pred = lreg.predict(X)
    data_prediction = lreg.predict_proba(X)
    trainacc = lreg.score(X,y)
    return pred, data_prediction, trainacc

mat = scipy.io.loadmat('../machine-learning-ex3/ex3/ex3data1.mat')
mat['y'][mat['y'][:]==10]=0 # this sets character identifier 10 to 0
#mat['y'] = mat['y'] % 10 # this is another way of setting 10 to 0
num_labels=10 # number of classes

X = mat['X']
y = mat['y']

# Although PolynomialFeatures could cope with it, we avoid using polynomial features as we have many (400), not only 2 variates in each sample.
#degree=6
#X=mapFeature(X[:,0], X[:,1], degree)

# Regularised logistic regression

# regularisation parameter
lambda0 = 1 # 1e-2 is a better value; set to tiny value (e.g. 1e-10) to achieve no regularisation

start_time = time.time()

# Option 1
#pred, data_prediction = reglogreg_manual(X, y, num_labels, lambda0) # takes 3.04 sec with lambda0=1, 8 sec with lambda0=1e-2

# Option 2
# https://stackoverflow.com/questions/843277/how-do-i-check-if-a-variable-exists#843293
if 'trainacc' in globals():
    del trainacc
pred, data_prediction, trainacc = reglogreg(X, y, lambda0) # takes 2.99 sec with lambda0=1, 7.7 sec with lambda0=1e-2
print('Time elapsed: {:.2f} sec'.format(time.time() - start_time))

print('{0} data points out of {1} correctly classified.'.format(np.sum(np.ravel(y)==pred),X.shape[0]))
print('Train Accuracy:')

if 'trainacc' in globals():
    print(trainacc * 100, 'percent')
#else: # This is an alternative calculation.
print(np.mean(np.ravel(y)==pred) * 100, 'percent')
print('Expected accuracy (with lambda = 1): 94.9 (approx)')


import sys
import os
import numpy as np
import pytest

sys.path.append('..')
import autodiff.optimize as optimize

def test_find_minimum():
    def test_func(args):
        return 2 * (args[0] ** 2) + 3 * (args[1] ** 2)

    assert(np.isclose(optimize.gradient_descent(test_func, [2, 100])[0], [0, 0]).all())
    assert(np.isclose(optimize.quasi_newtons_method(test_func, [2, 100], method = 'BFGS')[0], [0, 0]).all())
    assert(np.isclose(optimize.quasi_newtons_method(test_func, [2, 100], method = 'DFP')[0], [0, 0]).all())
    assert(np.isclose(optimize.quasi_newtons_method(test_func, [2, 100], method = 'Broyden')[0], [0, 0]).all())

    assert(np.isclose(optimize.gradient_descent(test_func, [100, 2])[0], [0, 0]).all())
    assert(np.isclose(optimize.quasi_newtons_method(test_func, [100, 2], method = 'BFGS')[0], [0, 0]).all())
    assert(np.isclose(optimize.quasi_newtons_method(test_func, [100, 2], method = 'DFP')[0], [0, 0]).all())
    assert(np.isclose(optimize.quasi_newtons_method(test_func, [100, 2], method = 'Broyden')[0], [0, 0]).all())

    assert(np.isclose(optimize.gradient_descent(test_func, [-100, 100])[0], [0, 0]).all())
    assert(np.isclose(optimize.quasi_newtons_method(test_func, [-100, 100], method = 'BFGS')[0], [0, 0]).all())
    assert(np.isclose(optimize.quasi_newtons_method(test_func, [-100, 100], method = 'DFP')[0], [0, 0]).all())
    assert(np.isclose(optimize.quasi_newtons_method(test_func, [-100, 100], method = 'Broyden')[0], [0, 0]).all())

    assert(np.isclose(optimize.gradient_descent(test_func, [0.4242, -0.54234])[0], [0, 0]).all())
    assert(np.isclose(optimize.quasi_newtons_method(test_func, [0.4242, -0.54234], method = 'BFGS')[0], [0, 0]).all())
    assert(np.isclose(optimize.quasi_newtons_method(test_func, [0.4242, -0.54234], method = 'DFP')[0], [0, 0]).all())
    assert(np.isclose(optimize.quasi_newtons_method(test_func, [0.4242, -0.54234], method = 'Broyden')[0], [0, 0]).all())

    def test_func2(args):
        return (args[0] - 5) ** 2

    assert(np.isclose(optimize.gradient_descent(test_func2, [1])[0], [5]).all())
    assert(np.isclose(optimize.quasi_newtons_method(test_func2, [1], method = 'BFGS')[0], [5]).all())
    assert(np.isclose(optimize.quasi_newtons_method(test_func2, [1], method = 'DFP')[0], [5]).all())
    assert(np.isclose(optimize.quasi_newtons_method(test_func2, [1], method = 'Broyden')[0], [5]).all())

    assert(np.isclose(optimize.gradient_descent(test_func2, [-0.534])[0], [5]).all())
    assert(np.isclose(optimize.quasi_newtons_method(test_func2, [-0.534], method = 'BFGS')[0], [5]).all())
    assert(np.isclose(optimize.quasi_newtons_method(test_func2, [-0.534], method = 'DFP')[0], [5]).all())
    assert(np.isclose(optimize.quasi_newtons_method(test_func2, [-0.534], method = 'Broyden')[0], [5]).all())

    assert(np.isclose(optimize.gradient_descent(test_func2, [20])[0], [5]).all())
    assert(np.isclose(optimize.quasi_newtons_method(test_func2, [20], method = 'BFGS')[0], [5]).all())
    assert(np.isclose(optimize.quasi_newtons_method(test_func2, [20], method = 'DFP')[0], [5]).all())
    assert(np.isclose(optimize.quasi_newtons_method(test_func2, [20], method = 'Broyden')[0], [5]).all())

    def rosenbrock(args, a = 2, b = 3):
        return (a - args[0]) ** 2 + b * (args[1] - args[0] ** 2) ** 2

    assert(np.isclose(optimize.gradient_descent(rosenbrock, [1, 1])[0], [2, 4]).all())
    assert(np.isclose(optimize.quasi_newtons_method(rosenbrock, [1, 1], method = 'BFGS')[0], [2, 4]).all())
    assert(np.isclose(optimize.quasi_newtons_method(rosenbrock, [1, 1], method = 'DFP')[0], [2, 4]).all())
    assert(np.isclose(optimize.quasi_newtons_method(rosenbrock, [1, 1], method = 'Broyden')[0], [2, 4]).all())

    assert(np.isclose(optimize.gradient_descent(rosenbrock, [2, 3])[0], [2, 4]).all())
    assert(np.isclose(optimize.quasi_newtons_method(rosenbrock, [2, 3], method = 'BFGS')[0], [2, 4]).all())
    assert(np.isclose(optimize.quasi_newtons_method(rosenbrock, [2, 3], method = 'DFP')[0], [2, 4]).all())
    assert(np.isclose(optimize.quasi_newtons_method(rosenbrock, [2, 3], method = 'Broyden')[0], [2, 4]).all())

    def test_func3(x):
        x = x[0]
        return np.array([x**3 -1])

    assert (np.isclose(optimize.newtons_method(test_func3,[5], method="inverse", max_iter= 1000)[0][0], 1.0))
    assert (np.isclose(optimize.newtons_method(test_func3,[5], method="exact", max_iter= 1000)[0][0], 1.0))
    assert (np.isclose(optimize.newtons_method(test_func3,[5], method="gmres", max_iter= 1000)[0][0], 1.0))
    assert (np.isclose(optimize.newtons_method(test_func3,[5], method="gmres_action", max_iter= 1000)[0][0], 1.0))

    def test_func4(x):
        x1 = x[0]
        x2 = x[1]
        return np.array([ 4 + 8*(x1**2) - (x1**4), 4 + 8*(x2**2) - (x2**4)])

    assert (np.isclose(optimize.newtons_method(test_func4, [-3,3], method="inverse", max_iter= 1000)[0] , [-2.91069338,  2.91069338]))[0]
    assert (np.isclose(optimize.newtons_method(test_func4, [-3,3], method="exact", max_iter= 1000)[0] , [-2.91069338,  2.91069338]))[0]
    assert (np.isclose(optimize.newtons_method(test_func4, [-3,3], method="gmres", max_iter= 1000)[0] , [-2.91069338,  2.91069338]))[0]
    assert (np.isclose(optimize.newtons_method(test_func4, [-3,3], method="gmres_action", max_iter= 1000)[0] , [-2.91069338,  2.91069338]))[0]

    def test_func5(x):
        x1 = x[0]
        x2 = x[1]
        x3 = x[2]
        return np.array([x1 + x1 + 1, x2 ** 3 - 3 * x2 - 3, -3 * x3 + 1])

    assert (np.isclose(optimize.newtons_method(test_func5, [5, 4, 5], method="inverse", max_iter=1000)[0],
                       [-0.5, 2.1038034, 0.33333333]))[0]
    assert (np.isclose(optimize.newtons_method(test_func5, [5, 4, 5], method="exact", max_iter=1000)[0],
                       [-0.5, 2.1038034, 0.33333333]))[0]
    assert (np.isclose(optimize.newtons_method(test_func5, [5, 4, 5], method="gmres", max_iter=1000)[0],
                       [-0.5, 2.1038034, 0.33333333]))[0]
    assert (np.isclose(optimize.newtons_method(test_func5, [5, 4, 5], method="gmres_action", max_iter=1000)[0],
                       [-0.5, 2.1038034, 0.33333333]))[0]

    def test_func6(x):
        x1 = x[0]
        return np.array([(x1 ** 2) + 3])

    with pytest.raises(RuntimeError):
        optimize.newtons_method(test_func6, [5], method="gmres", max_iter= 1000)

    with pytest.raises(RuntimeError):
        optimize.newtons_method(test_func6, [5], method="gmres_action", max_iter=1000)

    with pytest.raises(Exception):
        optimize.newtons_method(test_func6, [5,5,5], method="gmres", max_iter= 1000)

    with pytest.raises(Exception):
        optimize.newtons_method(test_func6, [5,5,5], method="gkkk", max_iter= 1000)

    with pytest.raises(Exception):
        optimize.quasi_newtons_method(rosenbrock, [2, 3], method='gfdgh')


import numpy as np
from math import atan2, asin

def Euler2Quaternion(phi, theta, psi):
    cth = np.cos(theta/2)
    cph = np.cos(phi/2)
    cps = np.cos(psi/2)

    sth = np.sin(theta/2)
    sph = np.sin(phi/2)
    sps = np.sin(psi/2)

    e0 = cps*cth*cph+sps*sth*sph
    e1 = cps*cth*sph-sps*sth*cph
    e2 = cps*sth*cph+sps*cth*sph
    e3 = sps*cth*cph+cps*sth*sph
    e = np.array([e0,e1,e2,e3])
    return e

def Quaternion2Euler(e):
    e0 = e.item(0)
    e1 = e.item(1)
    e2 = e.item(2)
    e3 = e.item(3)

    phi = atan2(2*(e0*e1 + e2*e3),(e0**2+e3**2-e1**2-e2**2))
    theta = asin(2*(e0*e2-e1*e3))
    psi = atan2(2*(e0*e3 + e1*e2),(e0**2+e1**2-e2**2-e3**2))
    return [phi,theta,psi]

def Quaternion2Rotation(e):
    e0 = e.item(0)
    e1 = e.item(1)
    e2 = e.item(2)
    e3 = e.item(3)

    R = np.array([[e0**2 + e1**2 - e2**2 - e3**2, 2*(e1*e2 - e0*e3), 2*(e1*e3 + e0*e2)],
                  [2*(e1*e2 + e0*e3), e0**2 - e1**2 + e2**2 - e3**2, 2*(e2*e3 - e0*e1)],
                  [2*(e1*e3 - e0*e2), 2*(e2*e3 + e0*e1), e0**2 - e1**2 - e2**2 + e3**2]
                  ])
    return R


# %%
'''
# General Relativity
'''

# %%
import numpy as np
import matplotlib.pyplot as plt
from functools import partial
import ipywidgets

def gamma(b):
    return 1/np.sqrt(1-b**2)

# %%
'''
### Hw1.3

How does an isotropically emitting gamma source look like from the point of view of a moving observer?
'''

# %%
@np.vectorize
def theta(theta_prime,beta):
    """
    Returns the angle of the radiation,
    emitted by the moving observer O' at an angle theta_prime,
    as seen by the stationary observer O,
    if the relative speed between O and O' is beta*c.
    """

    s = np.sin(theta_prime)/(gamma(beta)*(1 + np.cos(theta_prime)*beta))
    c = (np.cos(theta_prime) + beta)/(1 + np.cos(theta_prime)*beta)
    if s >= 0:
        return np.arccos(c)
    else:
        return 2*np.pi - np.arccos(c)

# %%
# varying beta

theta_prime = np.pi/2

betas = np.arange(0,1,0.01)

thetas = [theta(theta_prime=theta_prime,beta=b) for b in betas]
thetas = np.array(thetas)

plt.figure()
plt.plot(betas,thetas)
plt.xlabel('beta')
plt.ylabel('theta')
plt.show()

# %%
# varying theta_prime

beta = 0.9

theta_primes = np.arange(0,2*np.pi,2*np.pi/100)

thetas = [theta(theta_prime=t,beta=beta) for t in theta_primes]
thetas = np.array(thetas)

plt.figure()
plt.plot(theta_primes*180/np.pi,thetas*180/np.pi)
plt.xlabel('theta\'')
plt.ylabel('theta')
plt.show()

# %%
# multiple rays

n_rays = 16

theta_primes = np.arange(0,2*np.pi,2*np.pi/n_rays)

def plot_rays(beta):

    thetas = [theta(theta_prime=t,beta=beta) for t in theta_primes]
    thetas = np.array(thetas)

    plt.figure()
    for t in thetas:
        plt.plot([0,np.cos(t)],[0,np.sin(t)])
    plt.show()

ipywidgets.interact(plot_rays, beta = (0,0.99,0.01))

# %%
# Intensity

n_rays = 16
amp_factor = 1000

theta_primes = np.arange(0,np.pi,np.pi/(amp_factor*n_rays))
theta_scan = np.arange(0,np.pi+np.pi/n_rays,np.pi/n_rays)

def plot_intensity(beta):

    thetas = [theta(theta_prime=t,beta=beta) for t in theta_primes]
    thetas = np.array(thetas)

    intensity = np.zeros_like(theta_scan)

    j = 0
    last_i = 0
    for i,t in enumerate(thetas):
        if j >= len(intensity):
                print('error')
                break
        if t > theta_scan[j]:
            #print(i)
            intensity[j] = i - last_i
            last_i = i
            j += 1
    intensity[-1] = n_rays*amp_factor - last_i
    2
    intensity /= 1.*n_rays*amp_factor

    plt.figure()
    plt.plot(theta_scan[1:]*180/np.pi,intensity[1:])
    plt.xlabel('theta')
    plt.ylabel('normalized intensity')
    plt.title('angular spectrum')
    plt.show()

#plot_intensity(0.3)

ipywidgets.interact(plot_intensity, beta = (0,0.99,0.01))

# %%
# accounting for 3-dimensionality

n_rays = 16
amp_factor = 1000

theta_primes = np.arange(0,np.pi,np.pi/(amp_factor*n_rays))
theta_scan = np.arange(0,np.pi+np.pi/n_rays,np.pi/n_rays)

def plot_intensity(beta):

    thetas = [theta(theta_prime=t,beta=beta) for t in theta_primes]
    thetas = np.array(thetas)

    intensity = np.zeros_like(theta_scan)

    j = 0
    for i,t in enumerate(thetas):
        if j >= len(intensity):
                print('error')
                break
        intensity[j] += (0.00001 + np.sin(theta_primes[i]))/(0.0001 + np.sin(theta_scan[j]))
        if t > theta_scan[j]:
            #print(i)
            j += 1

    s = sum(intensity)
    print(intensity,s)
    intensity /= 1.*s

    plt.figure()
    plt.semilogy(theta_scan[1:]*180/np.pi,intensity[1:])
    plt.xlabel('theta')
    plt.ylabel('normalized intensity')
    plt.title('angular spectrum')
    plt.show()

# plot_intensity(0.)

ipywidgets.interact(plot_intensity, beta = (0,0.99,0.01))

# %%
# just to clarify how (arc)cos and (arc)sin work

theta_primes = np.arange(0,2*np.pi,2*np.pi/100)

plt.figure()
plt.plot(theta_primes,np.arcsin(np.sin(theta_primes)), label = 'sin')
plt.plot(theta_primes,np.arccos(np.cos(theta_primes)), label = 'cos')
plt.legend()
plt.show()

# %%
# Analytical solution to the intensity problem:
# assume in its own frame the source emits energy isotropically:
# what is the angular distribution seen by the observer?
# It will be cylindrically symmetric of course: what is the distribution wrt theta?

import sympy as sp
sp.init_printing()

v = sp.symbols('v', real=True)
gamma_sp = 1 / sp.sqrt(1-v**2)

theta_prime = sp.symbols('theta_prime', real=True)

# angle in the observer frame O
theta_orig = sp.atan(1/gamma_sp/(1/sp.tan(theta_prime) + v/sp.sin(theta_prime)))

# distribution means the derivative of theta in O wrt theta in O'
distribution = sp.diff(theta_orig, theta_prime)
# taking account of the size of the spherical portion.
# the absolute value is needed because of some issues with the arccosine and arccsine
# which are difficult to deal with in sympy
distribution_3d = sp.Abs(distribution * sp.sin(theta_orig) / sp.sin(theta_prime))

# %%
def plot_distribution(relative_velocity):

    # take the generic distributions and insert the actual velocity
    new_distribution = distribution.subs(v, relative_velocity)
    new_distribution_3d = distribution_3d.subs(v, relative_velocity)

    x = sp.symbols('x')

    # we make functions from the sympy relations, the inverse is
    # inserted because we want to plot d (theta_prime) / d (theta)
    f = sp.lambdify(x, 1/new_distribution.subs(theta_prime, x), 'numpy')
    f_3d = sp.lambdify(x, 1/new_distribution_3d.subs(theta_prime, x), 'numpy')

    theta_primes = np.linspace(1e-10, np.pi-1e-10)
    thetas = theta(theta_primes, relative_velocity)

    plt.ylabel("dtheta_prime/dtheta")
    plt.xlabel("theta")
    plt.semilogy(thetas, f(theta_primes), label="2d")
    plt.semilogy(thetas, f_3d(theta_primes), label="3d")
    plt.legend()
    plt.suptitle(f"relative velocity = {relative_velocity:.4f}")
    plt.show()

def log_plot(log_velocity):
    plot_distribution(1-10**(-log_velocity))

# ipywidgets.interact(plot_distribution, relative_velocity=(0,0.99,0.01), continuous_update=False)
ipywidgets.interact(log_plot, log_velocity=(0,2.5,0.05), continuous_update=False)

# %%


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

import numpy as np
import helper

def null_vector():
  # MISSING: Create a vector of size 10 and of type np.float32 full of zeros.
  return np.array([])

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

def polar(a):
  # MISSING: "a" is a Nx2 matrix representing cartesian coordinates,
  # convert them to polar coordinates.
  # This function should return a Nx2 matrix where:
  # - the first column is the radius.
  #  -the second column is the angle.
  return np.array([])

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

def moving_average(a):
  # MISSING: Compute the moving average of the elements of "a" over a
  # window of size 3.
  return np.array([])

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

if __name__ == '__main__':
  main()


"""
Supplemental functions for NumPy
"""
import numpy as np

def norm1d(array):
    shifted = array - (array.min())
    return shifted / shifted.max()

def scale1d(array, min=0, max=1):
    scaled = max * norm1d(array)
    return scaled + min

class PolynomialLinearModel:
    "A convenience class for creating polynomial linear models."
    def __init__(self, xs, ys, degree):
        (self.xs, self.ys) = (xs, ys)
        self.degree = degree
        self.y_mean = self.get_y_mean()
        (self.results, self.model, self.ys_predicted,
         self.ss_tot, self.ss_reg, self.ss_res,
         self.r_squared) = (None, None, None, None, None, None, None)
        (self.coeffs, self.residuals, self.rank,
         self.singular_values, self.rcond) = (None, None, None, None, None)
        self.polyfit()

    def polyfit(self):
        (self.coeffs, self.residuals, self.rank,
        self.singular_values, self.rcond) = np.polyfit(
            self.xs, self.ys, self.degree, full=True)
        self.model = np.poly1d(self.coeffs)
        self.ys_predicted = self.model(self.xs)
        self.ss_tot = self.get_ss_tot()
        self.ss_reg = self.get_ss_reg()
        self.ss_res = self.get_ss_res()
        self.r_squared = self.get_r_squared()
        self.results = {
            "coeffs": self.coeffs.tolist(),
            "residuals": self.residuals.tolist(),
            "rank": self.rank,
            "singular-values": self.singular_values.tolist(),
            "rcond": float(self.rcond),
            "y-mean": float(self.y_mean),
            "ss-tot": float(self.ss_tot),
            "ss-reg": float(self.ss_reg),
            "ss-res": float(self.ss_res),
            "r-squared": float(self.r_squared)}

    def predict(self, xs):
        return self.model(xs)

    def get_y_mean(self):
        return self.ys.sum() / self.ys.size

    def get_ss_tot(self):
        return ((self.ys - self.get_y_mean()) ** 2).sum()

    def get_ss_reg(self):
        return ((self.ys_predicted - self.get_y_mean()) ** 2).sum()

    def get_ss_res(self):
        return ((self.ys - self.ys_predicted) ** 2).sum()

    def get_r_squared(self):
        return 1 - self.get_ss_res() / self.get_ss_tot()

    def __str__(self):
        return str(self.results)

    def __repr__(self):
        return self.__str__()


# supporting lib for kmeans clustering
# Nitin Borwankar
# Open Data Science Training

import numpy as np
from scipy.cluster.vq import kmeans,vq
from scipy.spatial.distance import cdist
import matplotlib.pyplot as plt

def load_data(fName = '../datasets/UN4col.csv'):
  fp = open(fName)
  XX = np.loadtxt(fp)
  fp.close()
  return XX

def run_kmeans(X, n=10):
  _K = range(1,n)

  # scipy.cluster.vq.kmeans
  _KM = [kmeans(X,k) for k in _K] # apply kmeans 1 to 10
  _centroids = [cent for (cent,var) in _KM]   # cluster centroids

  _D_k = [cdist(X, cent, 'euclidean') for cent in _centroids]

  _cIdx = [np.argmin(D,axis=1) for D in _D_k]
  _dist = [np.min(D,axis=1) for D in _D_k]
  _avgWithinSS = [sum(d)/X.shape[0] for d in _dist]

  return (_K, _KM, _centroids, _D_k, _cIdx, _dist, _avgWithinSS)

def plot_elbow_curve(kIdx, K, avgWithinSS):
  fig = plt.figure()
  ax = fig.add_subplot(111)
  ax.plot(K, avgWithinSS, 'b*-')
  ax.plot(K[kIdx], avgWithinSS[kIdx], marker='o', markersize=12,
      markeredgewidth=2, markeredgecolor='r', markerfacecolor='None')
  plt.grid(True)
  plt.xlabel('Number of clusters')
  plt.ylabel('Average within-cluster sum of squares')
  tt = plt.title('Elbow for KMeans clustering')
  return(fig,ax)

def plot_clusters(orig,pred,nx,ny,legend=True):
  data = orig
  import matplotlib.pyplot as plt
  ylabels = { 0:'Male life expectancy in yrs',1:'Female life expectancy in yrs',2:'Infant mortality, per 1000'}
  # plot data into three clusters based on value of c
  p0 = plt.plot(data[pred==0,nx],data[pred==0,ny],'ro',label='Underdeveloped')
  p2 = plt.plot(data[pred==2,nx],data[pred==2,ny],'go',label='Developing')
  p1 = plt.plot(data[pred==1,nx],data[pred==1,ny],'bo',label='Developed')

  lx = p1[0].axes.set_xlabel('Per Capita GDP in US$')
  ly = p1[0].axes.set_ylabel(ylabels[ny])
  tt= plt.title('UN countries Dataset, KMeans clustering with K=3')
  if legend:
    ll=plt.legend()
  return (p0,p1,p2)


#!/usr/bin/env python3

import numpy as np
import math
import argparse
import pathlib
import os

def get_primes_from_2_to(n_):
    """ Input n>=6, Returns a array of primes, 2 <= p <= n """
    n_ += 1
    sieve = np.ones(n_//3 + (n_%6==2), dtype=np.bool)
    for i in range(1,int(n_**0.5)//3+1):
        if sieve[i]:
            k=3*i+1|1
            sieve[       k*k//3     ::2*k] = False
            sieve[k*(k-2*(i&1)+4)//3::2*k] = False
    return np.r_[2,3,((3*np.nonzero(sieve)[0][1:]+1)|1)]

def get_primes(min_, max_, step_):
    primes = get_primes_from_2_to(max_)

    if len(primes) == 0 or primes[-1] < min_:
        return []

    i = 0
    while i < len(primes)-1 and primes[i] < min_:
        i += 1

    filtered_primes = [primes[i]]

    if i < len(primes)-1:
        j = i + 1
        while j < len(primes) and primes[j] <= max_:
            if primes[j] >= primes[i] + step_:
                filtered_primes.append(primes[j])
                i = j
                j = i + 1
            else:
                j += 1

    filtered_primes = np.array(filtered_primes, dtype=np.int64)
    return filtered_primes

def is_prime(n_):
    if n_ == 2:
        return True
    if n_ % 2 == 0 or n_ <= 1:
        return False

    sqr = int(math.sqrt(n_)) + 1

    for divisor in range(3, sqr, 2):
        if n_ % divisor == 0:
            return False
    return True

def check(primes_, args_):
    for p in primes_:
        assert(is_prime(p))
        assert(p >= args_.min)
        assert(p <= args_.max)

def write_hpp(fname_, string_):
    with open(fname_, 'w+') as f:
        f.write(string_)
        print("file generated at: " + fname_)

# default parameters
class defaults:
    step = 131072
    max = 17177772037
    min = step

# parse args
parser = argparse.ArgumentParser(description='generate include/warpcore/primes.hpp', formatter_class=argparse.ArgumentDefaultsHelpFormatter)

parser.add_argument('--min', type=int, nargs='?', const=defaults.min, default=defaults.min, help="lower bound of primes to consider")
parser.add_argument('--max', type=int, nargs='?', const=defaults.max, default=defaults.max, help="upper bound of primes to consider")
parser.add_argument('-s', '--step', type=int, nargs='?', const=defaults.step, default=defaults.step, help="minimum offset between consecutive primes")
parser.add_argument('-r', '--replace', action='store_true', help="replace existing .hpp file")
parser.add_argument('-f', '--force_replace', action='store_true', help="replace existing .hpp without asking")
parser.add_argument('--no_check', action='store_true', help="do not check for validity")

args = parser.parse_args()

# constraints
assert(args.step <= args.min <= args.max)
assert(args.min >= 6)

# file header
string  = "#ifndef WARPCORE_PRIMES_HPP\n"
string += "#define WARPCORE_PRIMES_HPP\n\n"
string += "// This file has been generated by utils/generate_primes_hpp.py\n// with the following set of parameters: "
string += "(min=" + str(args.min) + ", max=" + str(args.max) + ", step=" + str(args.step) + ")\n\n"
string += "#include <array>\n"
string += "#include <cstdint>\n\n"
string += "namespace warpcore\n{\n\n"
string += "namespace detail\n{\n\n"
string += "// prime numbers with ~" + str(args.step) + " offset\n"

# static array of primes
primes = get_primes(args.min, args.max, args.step)
assert(len(primes) != 0)

# check if generated are primes an are in valid range
if not args.no_check:
    check(primes, args)

string += "constexpr std::array<std::uint64_t, " + str(len(primes)) + "> primes = \n{\n"

# insert primes into std::array
for p in primes[:-1]:
    string += "    " + str(p) + ",\n"
string += "    " + str(primes[-1]) + "\n};\n\n"

# file footer
string += "} // namespace detail\n\n"
string += "} // namespace warpcore\n\n"
string += "#endif /* WARPCORE_PRIMES_HPP */"

# pass output to stdio or replace .hpp file
if args.replace or args.force_replace:
    fname = str(pathlib.Path(__file__).absolute().parents[1]) + "/include/warpcore/primes.hpp"

    if os.path.isfile(fname):
        if not args.force_replace:
            while True:
                choice = input("file already exists. replace? [y,n]: ")
                if choice is 'y':
                    write_hpp(fname, string)
                    break
                elif choice is 'n':
                    print(string)
                    break
                else:
                    print("please answer with y or n")
        else:
            write_hpp(fname, string)
    else:
        write_hpp(fname, string)
else:
    print(string)


# A first simple TensorFlow learner
#
# Given some random samples of 2D data points (x,y),
# the following TF script tries to find a line
# that best describes the data points in terms of
# a minimal sum of squared errors (SSE)
#
# by Prof. Dr. Juergen Brauer, www.juergenbrauer.org

import tensorflow as tf
import numpy as np

# 1.1 create 1D array with 100 random numbers drawn uniformly from [0,1)
x_data = np.random.rand(100)
print("\nx_data:", x_data)
print("data type:", type(x_data))

# 1.2 now compute the y-points
y_data = x_data * 1.2345 + 0.6789
print("y_data:", y_data)

# so now we have ground truth samples (x,y)
# and the TF learner will have to estimate the line parameters
# y=W*x+b with W=1.2345 and b=0.6789
#
# These parameters are called variables in TF.

# 2. We initialize them with a random W and b=0
W = tf.Variable(tf.random_uniform([1], -1.0, 1.0))
b = tf.Variable(tf.zeros([1]))
y = W * x_data + b

# 3.1 Now define what to optimize at all:
#     here we want to minimize the SSE.
#     This is our "loss" of a certain line model
loss_func = tf.reduce_mean(tf.square(y - y_data))

# 3.2 We can use different optimizers in TF for model learning
my_optimizer = tf.train.GradientDescentOptimizer(0.5)

# 3.3 Tell the optimizer object to minimize the loss function
train = my_optimizer.minimize(loss_func)

# 4. Before starting, we have to initialize the variables
init = tf.global_variables_initializer()

# 5. Now distribute the graph to the computing hardware
sess = tf.Session()

# 6. Initialize the graph
sess.run(init)

# 7. Print inial value of W and b
print("\n")
print("initial W", sess.run(W))
print("initial b", sess.run(b))

# 8. For 200 steps...
print("\n")
for step in range(201):

    # 8.1 Do another gradient descent step to come to a better
    #     W and b
    sess.run(train)

    # 8.2 From time to time, print the current value of W and b
    if step % 10 == 0:
        print(step, sess.run(W), sess.run(b))

A first simple TensorFlow example/a_first_simple_tensorflow_example.py


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

def build_householder(a):
    """Return factors of householder matrix (I - tau * vv.T).

    This algorithm refers to the folloing article:
        G.H Golub and C.F Van Loan,
        "Matrix Computations 4th Edition", 2013.

    Arguments:
        a (array_like): A vector.

    Returns:
        v (numpy.ndarray): Householder vector.
            This vector is modified so that the 1st element is 1.
            See the reference for more details.
        tau (float): A coefficient of householder matrix.
        diagonal (float): A diagonal value which is result of householder
            transformation.
    """
    v = np.array(a, dtype=np.float)
    if v.ndim != 1:
        raise ValueError("vector must be 1 dimensional array")
    # build v and tau
    diagonal = np.linalg.norm(v)
    if v[0] >= 0:
        v[0] += diagonal
        diagonal = -diagonal
    else:
        v[0] -= diagonal
    v /= v[0]
    tau = 2 / np.inner(v, v)

    return v, tau, diagonal

def triangularize(A):
    """Return result of applying householder transformation to a matrix.

    This algorithm refers to the folloing article:
        G.H Golub and C.F Van Loan,
        "Matrix Computations 4th Edition", 2013.

    Arguments:
        A (array_like): A matrix.

    Returns:
        A (numpy.ndarray): A upper trianglar matrix.
            This lower trianglar submatrix is overwritten by unit
            householder vectors. See the reference for more details.
    """
    A = np.array(A, dtype=np.float)
    if A.ndim != 2:
        raise ValueError("matrix must be 2 dimensional array")
    # triangularization
    m, n = A.shape
    mn = n if m > n else m - 1
    for j in range(mn):
        v, tau, A[j, j] = build_householder(A[j:, j])
        A[j + 1:, j] = v[1:]
        A[j:, j + 1:] -= np.outer(tau * v, np.dot(v, A[j:, j + 1:]))

    return A

def householder(A):
    """Return factors of QR factorization using householder transformation.

    This algorithm refers to the folloing article:
        G.H Golub and C.F Van Loan,
        "Matrix Computations 4th Edition", 2013.

    Arguments:
        A (array_like): A matrix.

    Returns:
        Q (numpy.ndarray): A orthogonal matrix.
        R (numpy.ndarray): A upper trianglar matrix.
    """
    R = np.array(A, dtype=np.float)
    if R.ndim != 2:
        raise ValueError("matrix must be 2 dimensional array")
    # initialization
    m, n = R.shape
    Q = np.identity(m)
    # factorization
    mn = n if m > n else m - 1
    for j in range(mn):
        v, tau, R[j, j] = build_householder(R[j:, j])
        R[j + 1:, j] = 0
        R[j:, j + 1:] -= np.outer(tau * v, np.dot(v, R[j:, j + 1:]))
        Q[:, j:] -= np.outer(tau * np.dot(Q[:, j:], v), v)

    return Q, R

def build_wy(A):
    """Return factors of WY representaion (I - WY.T).

    This algorithm refers to the folloing article:
        G.H Golub and C.F Van Loan,
        "Matrix Computations 4th Edition", 2013..

    Arguments:
        A (array_like): A matrix.

    Returns:
        W (numpy.ndarray): W matrix of WY representation.
        Y (numpy.ndarray): A unit lower trianglar matrix.
            This upper trianglar submatrix is overwritten by
            the result of applying tiangulation to A.
    """
    Y = np.array(A, dtype=np.float)
    if Y.ndim != 2:
        raise ValueError("matrix must be 2 dimensional array")
    # initialization
    m, n = Y.shape
    mn = n if m > n else m - 1
    v, tau, Y[0, 0] = build_householder(Y[:, 0])
    Y[1:, 0] = v[1:]
    Y[:, 1:] -= np.outer(tau * v, np.dot(v, Y[:, 1:]))
    W = (2 / np.inner(v, v) * v).reshape(-1, 1)
    # build W and Y
    for j in range(1, mn):
        v, tau, Y[j, j] = build_householder(Y[j:, j])
        Y[j + 1:, j] = v[1:]
        Y[j:, j + 1:] -= np.outer(tau * v, np.dot(v, Y[j:, j + 1:]))
        v = np.concatenate([np.zeros(j), v], axis=0)
        w = tau * (v - np.dot(W, np.dot(Y[j:, :j].T, v[j:])))
        W = np.concatenate([W, w.reshape((-1, 1))], axis=1)

    return W, Y

def wy(A, panels=64):
    """Return factors of QR factorization using WY representaion (I - WY.T).

    This algorithm refers to the folloing article:
        G.H Golub and C.F Van Loan,
        "Matrix Computations 4th Edition", 2013.

    Arguments:
        A (array_like): A matrix.
        panels (int, optional): A panel size (column size).

    Returns:
        Q (numpy.ndarray): A orthogonal matrix.
        R (numpy.ndarray): A upper trianglar matrix.
    """
    R = np.array(A, dtype=np.float)
    if R.ndim != 2:
        raise ValueError("matrix must be 2 dimensional array")
    # initialization
    m, n = R.shape
    Q = np.identity(m)
    # block householder QR factorization
    j = 0
    mn = n if m > n else m - 1
    while j < mn:
        b = min(j + panels, mn)
        W, R[j:, j:b] = build_wy(R[j:, j:b])
        Y = np.tril(R[j:, j:b], k=-1) + np.eye(m - j, b - j)
        Q[:, j:] -= np.dot(np.dot(Q[:, j:], W), Y.T)
        R[j:, b:] -= np.dot(Y, np.dot(W.T, R[j:, b:]))
        R[j:, j:b] = np.triu(R[j:, j:b])
        j = b

    return Q, np.triu(R)

def build_compact_wy(A):
    """Return factors of Compact-WY representaion (I - YTY.T).

    This algorithm refers to the folloing article:
        Robert Schreiber and Charles Van Loan,
        "A Storage-Efficient WY Representation for Products of Householder
        Transformations", 1989.

    Arguments:
        A (array_like): A matrix.

    Returns:
        Y (numpy.ndarray): A unit lower trianglar matrix.
            This upper trianglar submatrix is overwritten by
            the result of applying tiangulation to A.
        T (numpy.ndarray): A upper triangular matrix.
    """
    Y = np.array(A, dtype=np.float)
    if Y.ndim != 2:
        raise ValueError("matrix must be 2 dimensional array")
    # initialization
    m, n = Y.shape
    mn = n if m > n else m - 1
    v, tau, Y[0, 0] = build_householder(Y[:, 0])
    Y[1:, 0] = v[1:]
    Y[:, 1:] -= np.outer(tau * v, np.dot(v, Y[:, 1:]))
    T = np.array([[2 / np.inner(v, v)]])
    # build Y and T
    for j in range(1, mn):
        v, tau, Y[j, j] = build_householder(Y[j:, j])
        Y[j + 1:, j] = v[1:]
        Y[j:, j + 1:] -= np.outer(tau * v, np.dot(v, Y[j:, j + 1:]))
        v = np.concatenate([np.zeros(j), v], axis=0)
        t = (-tau * np.dot(T, np.dot(Y[j:, :j].T, v[j:]))).reshape(-1, 1)
        T = np.block([[T, t], [np.zeros((1, j)), np.array([[tau]])]])

    return Y, T

def compact_wy(A, panels=64):
    """Return factors of QR factorization using Compact-WY
    representaion (I - YTY.T).

    This algorithm refers to the folloing article:
        Robert Schreiber and Charles Van Loan,
        "A Storage-Efficient WY Representation for Products of Householder
        Transformations", 1989.

    Arguments:
        A (array_like): A matrix.
        panels (int, optional): A panel size (column size).

    Returns:
        Q (numpy.ndarray): A orthogonal matrix.
        R (numpy.ndarray): A upper trianglar matrix.
    """
    R = np.array(A, dtype=np.float)
    if R.ndim != 2:
        raise ValueError("matrix must be 2 dimensional array")
    # initialization
    m, n = R.shape
    Q = np.identity(m)
    # block householder QR factorization
    j = 0
    mn = n if m > n else m - 1
    while j < mn:
        b = min(j + panels, mn)
        R[j:, j:b], T = build_compact_wy(R[j:, j:b])
        Y = np.tril(R[j:, j:b], k=-1) + np.eye(m - j, b - j)
        Q[:, j:] -= np.dot(np.dot(Q[:, j:], Y), np.dot(T, Y.T))
        R[j:, b:] -= np.dot(np.dot(Y, T.T), np.dot(Y.T, R[j:, b:]))
        R[j:, j:b] = np.triu(R[j:, j:b])
        j = b

    return Q, R


"""
    gradient descent method1：
    gradient methods with fixed step size
"""

import numpy as np

def main():

    x = np.random.rand(100)     # creat 100 numbers from 0 to 1.
    y = 10 + 5 * x              # creat a linear function

    print(len(x), len(y))
    epsilon = 0.01   # set threshold to stop loop

    cnt = 0
    alpha = 0.001   # set the step size of gradient update
    theta0 = 0      # x0=1, according to theta0
    theta1 = 0      # x1=xi

    error1 = 0
    error0 = 0

    while True:
        sum0 = 0
        sum1 = 0
        cnt = cnt + 1
        for i in range(0, len(x)):     # BGD method
            diff = y[i] - (theta0 + theta1 * x[i])  # gradient function

            sum0 = sum0 + diff          # theta0 derivative
            sum1 = sum1 + diff*x[i]     # theta1 derivative

        theta0 = theta0 + alpha * sum0/len(x)   # gradient update
        theta1 = theta1 + alpha * sum1/len(x)   # gradient update

        error1 = 0
        for i in range(0, len(x)):
            error1 = error1 + (y[i] - (theta0 + theta1 * x[i]))**2  # loss function

        if abs(error1) < epsilon:   # get a whole minimum numer
            print('error1-0:', abs(error1))
            break
        # if abs(error1-error0) < epsilon:   # get a relative minimum numer
        #     print('error1-0:', abs(error1))
        #     break

        else:
            error0 = error1     # get a relative minimum number
            print('error1:', error1)

        print('theta0:', theta0, 'theta1:', theta1)

if __name__ == '__main__':
    main()

gradient descent/gradient descent method1.py


import numpy as np

def B_mat_RM(x: list, y: list, xg:float, yg:float):
    """Computes strain-displacement matrix (B matrix) for bending moments
    and shear forces.

        Arg:
            x:     X coordinates of the element  [list]
            y:     Y coordinates of the element  [list]
            xg:    Gauss point - local X coordinate [float]
            yg:    Gauss point - local X coordinate [float]
        Returns:
            b_mat_b:    strain-displacement matrix for bending moments
            b_mat_s:    strain-displacement matrix for shear forces
            area:       area of the element
    """

    N = np.zeros((3, 1))
    N[0] = 1.0 - xg - yg
    N[1] = xg
    N[2] = yg

    loc_dxN = np.zeros((3, 1))
    loc_dxN[0] = -1.0
    loc_dxN[1] = 1.0
    loc_dxN[2] = 0.0

    loc_dyN = np.zeros((3, 1))
    loc_dyN[0] = -1.0
    loc_dyN[1] = 0.0
    loc_dyN[2] = 1.0

    jac_m = np.zeros((2, 2))
    jac_m[0, 0] = x[0]*loc_dxN[0] + x[1]*loc_dxN[1] + x[2]*loc_dxN[2]
    jac_m[0, 1] = y[0]*loc_dxN[0] + y[1]*loc_dxN[1] + y[2]*loc_dxN[2]
    jac_m[1, 0] = x[0]*loc_dyN[0] + x[1]*loc_dyN[1] + x[2]*loc_dyN[2]
    jac_m[1, 1] = y[0]*loc_dyN[0] + y[1]*loc_dyN[1] + y[2]*loc_dyN[2]

    jac_im = np.linalg.inv(jac_m)

    area = abs(jac_m[0, 0]*jac_m[1, 1] - jac_m[1, 0]*jac_m[0, 1]) / 2

    Ndx = np.zeros((3, 1))
    Ndx[0] = jac_im[0, 0]*loc_dxN[0] + jac_im[0, 1]*loc_dyN[0]
    Ndx[1] = jac_im[0, 0]*loc_dxN[1] + jac_im[0, 1]*loc_dyN[1]
    Ndx[2] = jac_im[0, 0]*loc_dxN[2] + jac_im[0, 1]*loc_dyN[2]

    Ndy = np.zeros((3, 1))
    Ndy[0] = jac_im[1, 0]*loc_dxN[0] + jac_im[1, 1]*loc_dyN[0]
    Ndy[1] = jac_im[1, 0]*loc_dxN[1] + jac_im[1, 1]*loc_dyN[1]
    Ndy[2] = jac_im[1, 0]*loc_dxN[2] + jac_im[1, 1]*loc_dyN[2]

    bmat_b1 = np.array(
        [[0, -Ndx[0, 0],         0],
         [0,         0,  -Ndy[0, 0]],
         [0, -Ndy[0, 0], -Ndx[0, 0]]])
    bmat_b2 = np.array(
        [[0, -Ndx[1, 0],         0],
         [0,         0,  -Ndy[1, 0]],
         [0, -Ndy[1, 0], -Ndx[1, 0]]])
    bmat_b3 = np.array(
        [[0, -Ndx[2, 0],         0],
         [0,         0,  -Ndy[2, 0]],
         [0, -Ndy[2, 0], -Ndx[2, 0]]])
    bmat_b = np.concatenate((bmat_b1, bmat_b2, bmat_b3), axis=1)

    bmat_s1 = np.array(
        [[Ndx[0, 0], -N[0, 0],        0],
         [Ndy[0, 0],        0, -N[0, 0]]])
    bmat_s2 = np.array(
        [[Ndx[1, 0], -N[1, 0],        0],
         [Ndy[1, 0],        0, -N[1, 0]]])
    bmat_s3 = np.array(
        [[Ndx[2, 0], -N[2, 0],        0],
         [Ndy[2, 0],        0, -N[2, 0]]])
    bmat_s = np.concatenate((bmat_s1, bmat_s2, bmat_s3), axis=1)

    return bmat_b, bmat_s, area

def NodeStress(D_mat_b, D_mat_s, xg, yg, u):
    """Computes stresses at the Gauss points and evaluates values to the nodes.

        Arg:
            D_mat_b:    X coordinates of the element  [list]
            D_mat_s:    Y coordinates of the element  [list]
            xg:         Gauss point - local X coordinate [float]
            yg:         Gauss point - local X coordinate [float]
            u:          Nodal displacements
        Returns:
            ndStress:   Nodal stress matrix
    """

    pass

def D_mat(h, E, mi):
    """Computes constitutive matrices for bending
    moments and shear forces of element.

        Arg:
            h:          Thickness of element  [m, float]
            E:          Young modulus of elasticity  [Pa, int]
            mi:         Poissons number [float]
        Returns:
            D_mat_b:    Constitutive matrix for bending moments
            D_mat_s:    Constitutive matrix for shear forces
    """

    D_mat_b = (h**3 / 12) * (E / (1 - mi**2)) * np.array(
        [[1, mi,   0],
         [mi, 1,   0],
         [0,  0,   (1-mi)/2]])

    D_mat_s = (h*5 / 6) * (E / (2*(1 + mi))) * np.array(
        [[1,  0],
         [0,  1]])

    return D_mat_b, D_mat_s


# matrix_determinant 练习测试,作用，返回方阵的行列式 .行列式的概念可参考：https://www.jianshu.com/p/0fd8ac349b5e
import tensorflow as tf
import numpy as np

# 方阵
data = np.mat([[11.1,12.1],
               [21.1,22.1]]);

with tf.Session() as sess:
    z = tf.matrix_determinant(data);
    print(sess.run(z));


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

import numpy as np

def rotx(t):
    """Creates a matrix that rotates t radians around the x axis."""
    c = np.cos(t)
    s = np.sin(t)
    return np.array([[1,  0,  0],
                     [0,  c, -s],
                     [0,  s,  c]])

def roty(t):
    """Creates a matrix that rotates t radians around the y axis."""
    c = np.cos(t)
    s = np.sin(t)
    return np.array([[c,  0,  s],
                     [0,  1,  0],
                     [-s, 0,  c]])

def rotz(t):
    """Creates a matrix that rotates t radians around the z axis."""
    c = np.cos(t)
    s = np.sin(t)
    return np.array([[c, -s,  0],
                     [s,  c,  0],
                     [0,  0,  1]])

def rot_matrix(rx, ry, rz):
    return rotz(rz).dot(roty(ry)).dot(rotx(rx))

def yaw_pitch_roll_from_rot_matrix(R):
    """Recovers yaw, pitch roll from a rotation matrix.

    Assumes rotation to have been
    applied in the order R = R_z * R_y * R_x.
    """
    yaw = np.arctan(R[1, 0] / R[0, 0])
    pitch = np.arctan(-R[2, 0] / np.sqrt(R[2, 1]**2 + R[2, 2]**2))
    roll = np.arctan(R[2, 1] / R[2, 2])
    return yaw, pitch, roll


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

x = np.linspace(-4, 4, num = 100)

constant = 1.0 / np.sqrt(2 * np.pi)
pdf_normal_distribution = constant * np.exp((-x ** 2) / 2.0)

fig, ax = plt.subplots(figsize=(10, 5))

ax.plot(x, pdf_normal_distribution)
ax.set_ylim(0)
ax.set_title('Normal Distribution', size=20)
ax.set_ylabel('Probability Density', size=20)

plt.show()


#importing libraries
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn import preprocessing
from sklearn.preprocessing import normalize

%matplotlib inline

#load dataset
dataset = pd.read_csv("/Users/samar/Documents/pythonwd/special-potato/AXISBANK.csv")

#Clean dataset
#adding t1 value or the next day value
dataset["t1"] = dataset["4. close"].shift(-1)

#removing last NaN - because nobody likes naan!
dataset = dataset[0:(dataset.shape[0]-1)]

#adding p1 as change between t1 and t0
dataset["p1"] = (dataset["t1"] - dataset["4. close"])

#changing p1 to 1 if change was +ve and 0 if - ve
dataset["p1"] = np.where(dataset["p1"] > 0, 1,0)

#cleaning out dates and dataframe
X = dataset[["1. open","2. high", "3. low" ,"4. close", "5. volume"]]

def normalize(df):
    G = preprocessing.StandardScaler().fit(df)
    ndf_mean = df- G.mean_
    ndf = ndf_mean/G.var_
    return ndf

X = normalize(X)

split = (int(X.shape[0]*(2/3)))
train_set_x = X[:split]
train_set_x = train_set_x.transpose()
train_set_x = train_set_x.values

test_set_x = X[split:]
test_set_x = test_set_x.transpose()
test_set_x = test_set_x.values

# similarly making y matrix with (1, m) size
Y = dataset[["p1"]]

train_set_y = Y[:split]
train_set_y = train_set_y.transpose()
train_set_y = train_set_y.values

test_set_y = Y[split:]
test_set_y = test_set_y.transpose()
test_set_y = test_set_y.values
#defining sigmoid function
def sigmoid(z):
    s = 1 / (1 + np.exp(-z))
    return s

def initialize_with_zeros(dim):
    w = np.zeros(shape=(dim, 1))
    b = 0
    return w, b

def propagate(w, b, X, Y):
    m = X.shape[1]
    A = sigmoid(np.dot(w.T, X) + b)  # compute activation
    cost = (- 1 / m) * np.sum(Y * np.log(A) + (1 - Y) * (np.log(1 - A)))  # compute cost
    dw = (1 / m) * np.dot(X, (A - Y).T)
    db = (1 / m) * np.sum(A - Y)
    cost = np.squeeze(cost)
    grads = {"dw": dw,
             "db": db}
    return grads, cost

def optimize(w, b, X, Y, num_iterations, learning_rate, print_cost = False):
    costs = []
    for i in range(num_iterations):
        grads, cost = propagate(w, b, X, Y)
        dw = grads["dw"]
        db = grads["db"]
        w = w - (learning_rate * dw)  # need to broadcast
        b = b - (learning_rate * db)
        if i % 100 == 0:
            costs.append(cost)
        if print_cost and i % 100 == 0:
            print ("Cost after iteration %i: %f" % (i, cost))
    params = {"w": w,
              "b": b}
    grads = {"dw": dw,
             "db": db}
    return params, grads, costs

def predict(w, b, X):
    m = X.shape[1]
    Y_prediction = np.zeros((1, m))
    w = w.reshape(X.shape[0], 1)
    A = sigmoid(np.dot(w.T, X) + b)
    for i in range(A.shape[1]):
        Y_prediction[0, i] = 1 if A[0, i] > 0.5 else 0
    return Y_prediction

def model(X_train, Y_train, X_test, Y_test, num_iterations=2000, learning_rate=0.5, print_cost=False):
    w, b = initialize_with_zeros(X_train.shape[0])
    parameters, grads, costs = optimize(w, b, X_train, Y_train, num_iterations, learning_rate, print_cost)
    w = parameters["w"]
    b = parameters["b"]
    Y_prediction_test = predict(w, b, X_test)
    Y_prediction_train = predict(w, b, X_train)
    print("train accuracy: {} %".format(100 - np.mean(np.abs(Y_prediction_train - Y_train)) * 100))
    print("test accuracy: {} %".format(100 - np.mean(np.abs(Y_prediction_test - Y_test)) * 100))
    d = {"costs": costs,
         "Y_prediction_test": Y_prediction_test,
         "Y_prediction_train" : Y_prediction_train,
         "w" : w,
         "b" : b,
         "learning_rate" : learning_rate,
         "num_iterations": num_iterations}
    return d

d = model(train_set_x, train_set_y, test_set_x, test_set_y, num_iterations = 2000, learning_rate = 0.005, print_cost = True)

# Plot learning curve (with costs)
costs = np.squeeze(d['costs'])
plt.plot(costs)
plt.ylabel('cost')
plt.xlabel('iterations (per hundreds)')
plt.title("Learning rate =" + str(d["learning_rate"]))
plt.show()


"""
Filename:     calc_fourier_transform.py
Author:       Damien Irving, irving.damien@gmail.com
Description:  Calculate Fourier transform

"""

# Import general Python modules

import sys, os, pdb
import argparse
import numpy, math
import xarray
from scipy import fftpack
from scipy import signal
from copy import deepcopy

# Import my modules

cwd = os.getcwd()
repo_dir = '/'
for directory in cwd.split('/')[1:]:
    repo_dir = os.path.join(repo_dir, directory)
    if directory == 'climate-analysis':
        break

modules_dir = os.path.join(repo_dir, 'modules')
sys.path.append(modules_dir)

try:
    import general_io as gio
    import convenient_universal as uconv
except ImportError:
    raise ImportError('Must run this script from anywhere within the climate-analysis git repo')

# Define functions

def filter_signal(signal, indep_var, min_freq, max_freq, exclusion, real=False):
    """Filter a signal by performing a Fourier Tranform and then
    an inverse Fourier Transform for a selected range of frequencies"""

    sig_fft, sample_freq = fourier_transform(signal, indep_var)
    filtered_signal = inverse_fourier_transform(sig_fft, sample_freq, min_freq=min_freq, max_freq=max_freq, exclude=exclusion)

    if real:
        filtered_signal = filtered_signal.real

    return filtered_signal

def fourier_transform(signal, indep_var):
    """Calculate the Fourier Transform.

    Args:
      signal (numpy.ndarray): Data to be transformed
      indep_var (list/tuple): Independent variable (i.e. 1 dimensional time axis or longitude axis)

    Returns:
      sig_fft (numpy.ndarray): Coefficients obtained from the Fourier Transform
      freqs (numpy.ndarray): Wave frequency associated with each coefficient

    """

    spacing = indep_var[1] - indep_var[0]
    sig_fft = fftpack.fft(signal)
    sample_freq = fftpack.fftfreq(len(indep_var), d=spacing) * len(indep_var) * spacing  #units = cycles per length of domain
    sample_freq = numpy.resize(sample_freq, sig_fft.shape)

    return sig_fft, sample_freq

def inverse_fourier_transform(coefficients, sample_freq,
                              min_freq=None, max_freq=None, exclude='negative'):
    """Inverse Fourier Transform.

    Args:
      coefficients (numpy.ndarray): Coefficients obtained from the Fourier Transform
      sample_freq (numpy.ndarray): Wave frequency associated with each coefficient
      max_freq, min_freq (float, optional): Exclude values outside [min_freq, max_freq]
        frequency range. (Note that this filtering keeps both the positive and
        negative half of the spectrum)
      exclude (str, optional): Exclude either the 'positive' or 'negative'
        half of the Fourier spectrum. (A Hilbert transform, for example, excludes
        the negative part of the spectrum)

    """

    assert exclude in ['positive', 'negative', None]

    coefs = deepcopy(coefficients)  # Deep copy to prevent side effects
                                    # (shallow copy not sufficient for complex
                                    # things like numpy arrays)

    if exclude == 'positive':
        coefs[sample_freq > 0] = 0
    elif exclude == 'negative':
        coefs[sample_freq < 0] = 0

    if (max_freq == min_freq) and max_freq:
        coefs[numpy.abs(sample_freq) != max_freq] = 0

    if max_freq:
        coefs[numpy.abs(sample_freq) > max_freq] = 0

    if min_freq:
        coefs[numpy.abs(sample_freq) < min_freq] = 0

    result = fftpack.ifft(coefs)

    return result

def first_localmax_index(data):
    """Return index of first local maxima.

    If there is no local maxima (e.g. if all the values are zero),
    it will simply return zero.

    """
    localmax_indexes = signal.argrelextrema(data, numpy.greater, mode='wrap')

    if localmax_indexes[0].size > 0:
        return localmax_indexes[0][0]
    else:
        return 0

def _get_coefficients(data, lon_axis,
                      min_freq, max_freq,
                      long_name, units,
                      outdata_dict):
    """Calculate magnitude and phase coefficients for each frequency."""

    exclusion = None
    for freq in range(min_freq, max_freq + 1):
        filtered_signal = numpy.apply_along_axis(filter_signal, -1,
                                                 data, lon_axis,
                                                 freq, freq,
                                                 exclusion, real=True)

        localmax_vals = numpy.max(filtered_signal, axis=-1)
        localmax_indexes = numpy.apply_along_axis(first_localmax_index, -1, filtered_signal)
        localmax_lons = map(lambda x: lon_axis[x], localmax_indexes)

        outdata_dict['wave'+str(freq)+'_amp'] = (localmax_vals, _coefficient_atts('amp', freq, long_name, units))
        outdata_dict['wave'+str(freq)+'_phase'] = (localmax_lons, _coefficient_atts('phase', freq, long_name, units))

    return outdata_dict

def _coefficient_atts(ctype, freq, orig_long_name, units):
    """Get the attributes for the coefficient output variable."""

    assert ctype in ('amp', 'phase')

    method = 'filtered'
    if ctype == 'amp':
        name = 'amplitude_of_'+method+'_'+orig_long_name
    elif ctype == 'phase':
        name = 'first_local_maxima_of_'+method+'_'+orig_long_name,

    atts = {'standard_name': name,
            'long_name': name,
            'units': units,
            'notes': _get_filter_text(method, freq, freq)}

    return atts

def extract_data(dset, inargs):
    """Extract the data from the input file."""

    subset_dict = gio.get_subset_kwargs(inargs)
    darray = dset[inargs.var].sel(**subset_dict)

    long_name = str(darray.attrs['long_name'])
    units = str(darray.attrs['units'])

    if inargs.avelat:
        darray = darray.mean('latitude')

    assert darray.dims[-1] == 'longitude', \
    'This script is setup to perform the fourier transform along the longitude axis'

    if inargs.valid_lon:
        start_lon, end_lon = inargs.valid_lon
        lon_vals = numpy.array([start_lon, end_lon, darray['longitude'].values.min()])
        assert numpy.sum(lon_vals >= 0) == 3, "Longitudes must be 0 to 360"
        darray.loc[dict(longitude=slice(0, start_lon))] = 0
        darray.loc[dict(longitude=slice(end_lon, 360))] = 0

    return darray, long_name, units

def _filter_data(data, lon_axis,
                 min_freq, max_freq,
                 var, long_name, units,
                 outtype, outdata_dict):
    """Filter data.

    Can perform either a hilbert transform (i.e. inverse Fourier transform
    for wavenumbers of interest) or go one step further and calculate the
    wave envelope.

    """

    assert outtype in ['envelope', 'hilbert']

    if outtype == 'envelope':
        exclusion = 'negative'
        method_short = 'env'
        method_long = 'wave_envelope'
    elif outtype == 'hilbert':
        exclusion = None
        method_short = 'ift'
        method_long = 'inverse_fourier_transformed'

    outdata = numpy.apply_along_axis(filter_signal, -1,
                                     data, lon_axis,
                                     min_freq, max_freq,
                                     exclusion)
    if outtype == 'envelope':
        outdata = 2 * numpy.abs(outdata)
    else:
        outdata = outdata.real

    filter_text = _get_filter_text(method_long, min_freq, max_freq)
    atts = {'standard_name': method_long+'_'+long_name,
            'long_name': method_long+'_'+long_name,
            'units': units,
            'notes': filter_text}

    outdata_dict[method_short+var] = (outdata, atts)

    return outdata_dict

def _get_filter_text(method, min_freq, max_freq):
    """Get the notes attribute text according to the analysis
    method and frequency range."""

    filter_text = '%s with frequency range: %s to %s' %(method, min_freq, max_freq)

    return filter_text

def spectrum(signal_fft, freqs, scaling='amplitude', variance=None):
    """Calculate the spectral density for a given Fourier Transform.

    Args:
      signal_fft, freqs (numpy.ndarray): Typically the output of fourier_transform()
      scaling (str, optional): Choices for the amplitude scaling for each frequency
        are as follows (see Wilks 2011, p440):
         'amplitude': no scaling at all (C)
         'power': sqaure the amplitude (C^2)
         'R2': variance explained = [(n/2)*C^2] / (n-1)*variance^2,
         where n and variance are the length and variance of the
         orignal data series (R2 = the proportion of the variance
         explained by each harmonic)

    """

    assert scaling in ['amplitude', 'power', 'R2']
    if scaling == 'R2':
        assert variance, \
        "To calculate variance explained must provide variance value"

    if len(signal_fft.shape) > 1:
        print "WARNING: Ensure that frequency is the final axis"

    # Calculate the entire amplitude spectrum
    n = signal_fft.shape[-1]
    amp = numpy.abs(signal_fft) / n

    # The positive and negative half are identical, so just keep positive
    # and double its amplitude
    freq_limit_index = int(math.floor(n / 2))
    pos_amp = 2 * numpy.take(amp, range(1, freq_limit_index), axis=-1)
    pos_freqs = numpy.take(freqs, range(1, freq_limit_index), axis=-1)

    if scaling == 'amplitude':
        result = pos_amp
    elif scaling == 'power':
        result = (pos_amp)**2
    elif scaling == 'R2':
        result = ((n / 2) * (pos_amp**2)) / ((n - 1) * (variance))

    return result, pos_freqs

def count_sign_change(data):
    """Count the number of times the data series changes sign.

    Works by determining the sign of all the values (-1, 0 or 1)
      and then replaces zeros with the next non-zero value, since
      -1 to/from 0 or 1 to/from 0 changes do not count as a sign
      change in this context.

    """

    assert data.ndim == 1, "Input array must be one dimensional"

    signs = numpy.sign(data)

    counter = -2
    while signs[-1] == 0:
        signs[-1] = signs[counter]
        counter = counter - 1

    for i in range(len(signs)):
        counter = 1
        while signs[i] == 0:
            signs[i] = signs[i+counter]
            counter = counter + 1

    diffs = numpy.abs(numpy.diff(signs))
    change_count = numpy.sum(diffs == 2)

    return change_count

def _get_sign_change(data, outdata_dict):
    """ """

    sign_change_data = numpy.apply_along_axis(count_sign_change, -1, data)

    sign_change_atts = {'standard_name': 'sign_change_count',
                        'long_name': 'sign_change_count',
                        'units': '',
                        'notes': 'count of number of times signal sign (pos/neg) changed'}

    outdata_dict['sign_count'] = (sign_change_data, sign_change_atts)

    return outdata_dict

def _get_env_max(data, lon_axis,
                 min_freq, max_freq,
                 units, outdata_dict):
    """Get the maximum envelope value."""

    outdata = numpy.apply_along_axis(filter_signal, -1,
                                     data, lon_axis,
                                     min_freq, max_freq,
                                     'negative')
    outdata = numpy.max(2 * numpy.abs(outdata), axis=-1)

    method_note = 'maximum value of wave envelope'
    filter_text = _get_filter_text(method_note, min_freq, max_freq)
    atts = {'standard_name': 'envelope_maximum',
            'long_name': 'envelope_maximum',
            'units': units,
            'notes': filter_text}

    outdata_dict['env_max'] = (outdata, atts)

    return outdata_dict

def main(inargs):
    """Run the program."""

    # Read the data
    dset_in = xarray.open_dataset(inargs.infile)
    gio.check_xarrayDataset(dset_in, inargs.var)
    darray, long_name, units = extract_data(dset_in, inargs)

    # Perform task
    outdata_dict = {}
    if inargs.outtype == 'coefficients':
        outdata_dict = _get_coefficients(darray.values, darray['longitude'].values,
                                         inargs.min_freq, inargs.max_freq,
                                         long_name, units, outdata_dict)
        if inargs.sign_change:
            outdata_dict = _get_sign_change(darray.values, outdata_dict)

        if inargs.env_max:
            env_max_min_freq, env_max_max_freq = inargs.env_max
            outdata_dict = _get_env_max(darray.values, darray['longitude'].values,
                                        env_max_min_freq, env_max_max_freq,
                                        units, outdata_dict)
        dims = darray.dims[:-1]
    else:
        outdata_dict = _filter_data(darray.values, darray['longitude'].values,
                                    inargs.min_freq, inargs.max_freq,
                                    inargs.var, long_name, units,
                                    inargs.outtype, outdata_dict)
        dims = darray.dims

    # Write the output file
    d = {}
    for dim in dims:
        d[dim] = darray[dim]

    for outvar in outdata_dict.keys():
        d[outvar] = (dims, outdata_dict[outvar][0])

    dset_out = xarray.Dataset(d)

    for outvar in outdata_dict.keys():
        dset_out[outvar].attrs = outdata_dict[outvar][1]

    gio.set_global_atts(dset_out, dset_in.attrs, {inargs.infile: dset_in.attrs['history'],})
    dset_out.to_netcdf(inargs.outfile)

if __name__ == '__main__':

    extra_info ="""
example (vortex.earthsci.unimelb.edu.au):
    /usr/local/uvcdat/1.5.1/bin/cdat calc_fourier_transform.py
    va_Merra_250hPa_30day-runmean-Jun2002_r360x181.nc va test.nc
    --filter 2 9 --outtype hilbert
author:
    Damien Irving, d.irving@student.unimelb.edu.au
notes:
    Note that the Hilbert transform excludes the negative half
    of the frequency spectrum and doubles the final amplitude. This does not
    give the same result as if you simply retain the negative half.
references:
    http://docs.scipy.org/doc/numpy/reference/routines.fft.html
    http://gribblelab.org/scicomp/09_Signals_sampling_filtering.html

"""

    description='Perform Fourier Transform along lines of constant latitude'
    parser = argparse.ArgumentParser(description=description,
                                     epilog=extra_info,
                                     argument_default=argparse.SUPPRESS,
                                     formatter_class=argparse.RawDescriptionHelpFormatter)

    parser.add_argument("infile", type=str, help="Input file name")
    parser.add_argument("var", type=str, help="Input file variable")
    parser.add_argument("outfile", type=str, help="Output file name")
    parser.add_argument("min_freq", type=int, help="Minimum frequency to retain")
    parser.add_argument("max_freq", type=int, help="Maximum frequency to retain (can equal min_freq for single freq)")
    parser.add_argument("outtype", type=str, choices=('hilbert', 'coefficients', 'envelope'),
                        help="Output can be a hilbert transform (i.e. inverse Fourier transform), wave envelope or magnitude and phase coefficients for each freq")

    parser.add_argument("--latitude", type=float, nargs=2, metavar=('START', 'END'),
                        help="Latitude range over which to perform Fourier Transform [default = entire]")
    parser.add_argument("--valid_lon", type=float, nargs=2, metavar=('START', 'END'), default=None,
                        help="Longitude range over which to perform Fourier Transform (all other values are set to zero) [default = entire]")
    parser.add_argument("--time", type=str, nargs=2, metavar=('START_DATE', 'END_DATE'),
                        help="Time period [default = entire]")

    parser.add_argument("--avelat", action="store_true", default=False,
                        help="Average the data over the latitude axis before performing Fourier transform")

    parser.add_argument("--sign_change", action="store_true", default=False,
                        help="for a coefficients outtype, add an extra output variable which represents the count of times the signal changes sign")
    parser.add_argument("--env_max", type=int, nargs=2, metavar=('MIN_FREQ', 'MAX_FREQ'), default=None,
                        help="for a coefficients outtype, add an extra output variable for the maximum envelope value")

    args = parser.parse_args()

    print 'Input files: ', args.infile
    print 'Output file: ', args.outfile

    main(args)


import numpy as np

from . import solve
from . factorization_QR import transform_Householder, retrieve_H

def power_method(A, u0=None, displace=0, max_step=10000, tolerance=1e-8, verbose=False, inverse=False, normalize=True):
    # power_method: return largest modulus eigenvalue and corresponding eigenvector
    # inverse = True: return smallest eig instead.
    m, n = A.shape
    assert m == n

    if u0 is None:
        u0 = np.ones(n)
    if displace != 0:
        A = A - displace * np.eye(m)

    u = u0
    step = 0
    while True:
        old_u = np.copy(u)

        if not inverse:
            y = A @ u
        else:
            # TODO: since A is fixed, we can save the LU decomposition and reuse to reduce computation.
            y = solve(A, u, method="PLU")

        mu = u[np.argmax(np.abs(u))]
        u = y / mu

        step += 1
        if step >= max_step:
            if verbose:
                print(f"Early stop at step {step}")
            break

        if np.linalg.norm(old_u-u, ord=1) < tolerance:
            if verbose:
                print(f"Covengent at step {step} under tolerance {tolerance}")
            break

    if inverse:
        mu = 1 / mu

    if displace != 0:
        mu += displace

    if normalize:
        u = u / np.linalg.norm(u, ord=np.inf)

    return mu, u

def eig_power(A):
    # return all eigenvalues and eigenvectors
    m, n = A.shape
    assert m == n

    mus = []
    us = []

    X = np.copy(A)
    for i in range(n):
        mu, u = power_method(X)

        mus.append(mu)
        us.append(u)

        H = retrieve_H(*transform_Householder(u))
        X = H @ X @ H
        X = X[1:, 1:]

    return mus, us


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

# In[491]:

import matplotlib.pyplot as plt
# ^^^ pyforest auto-imports - don't write above this line
import numpy as np
import pathlib
from skimage import color
import random

# In[253]:

defaultPath = r'G:\Documents\ReferenceBooks\1-DigitalImageProcessing\HW3\Images\\'

# ### Convert image to FFT

# In[362]:

class GrayImageFFT:
    def load_gray_from_file(self,defaultPath,fileName):
        self.image = plt.imread(defaultPath+fileName)
        self.image = color.rgb2gray(self.image)

    def load_from_array(self,array):
        self.image = array

    def fft(self):
        self.fft=np.fft.fft2(self.image)
        self.fft = np.fft.fftshift(self.fft)
        self.magnitude = 20*np.log(np.abs(self.fft))

        self.filtered = self.fft
        return self.magnitude

    def apply_filter(self,custom_filter):
        self.filtered = self.filtered*custom_filter

    def get_filtered_image(self):
        shifted= np.fft.ifftshift(self.filtered)
        return np.abs( np.fft.ifft2(shifted))

# ### Notch Filter

# In[335]:

def get_filter_from_point(shape,d0,u,v):
    length = shape[0]
    width = shape[1]
    my_array=np.indices((length,width))
    distance_uv = np.sqrt((my_array[0] -length/2 + u)**2 + (my_array[1]-width/2+v)**2)
    distance_muv = np.sqrt((my_array[0] -length/2 - u)**2 + (my_array[1]-width/2-v)**2)
    bandpass_filter= np.logical_or(distance_uv<=d0,distance_muv<=d0)
    notch_filter = np.invert( bandpass_filter)
    return notch_filter

# In[336]:

imagefft=GrayImageFFT()
imagefft.load_gray_from_file(defaultPath,'Vessel.png')

imagefft.fft()

H1 = get_filter_from_point(vessel.shape,  3,180, 128)
H2 = get_filter_from_point(vessel.shape, 3,-180, 128)
H3 = get_filter_from_point(vessel.shape, 3, 58, 128)
H4 = get_filter_from_point(vessel.shape, 3, -58, 128)
H5 = get_filter_from_point(vessel.shape,2,120,128)
H6 = get_filter_from_point(vessel.shape,2,-120,128)

NotchFilter = H1*H2*H3*H4*H5*H6

imagefft.apply_filter(NotchFilter)
back_image = imagefft.get_filtered_image()

plt.figure(figsize=(10,10))
plt.subplot(2,2,1)
plt.imshow(dft,cmap='gray')

plt.subplot(2,2,2)
plt.imshow(imagefft.magnitude*NotchFilter,cmap='gray')

plt.subplot(2,2,3)
plt.imshow(vessel,cmap='gray')

plt.subplot(2,2,4)
plt.imshow(back_image,cmap='gray')

plt.imsave(defaultPath+'VesselDFTAfterFix.png',imagefft.magnitude*NotchFilter,cmap='gray')
plt.imsave(defaultPath+'VesselDFT.png',imagefft.magnitude,cmap='gray')
plt.imsave(defaultPath+'VesselNotchFilter.png',back_image,cmap='gray')

# ### Gaussian Smoothing Filtering

# In[332]:

def gaussian_lowpass_filter(shape,sigma):
    indices=np.indices(dimensions=shape)
    distance=np.sqrt((indices[0]-shape[0]/2)**2+(indices[1]-shape[1]/2)**2)
    return np.exp(-1*distance**2/(2*sigma**2))

# In[367]:

nature=plt.imread(defaultPath+'Nature.jpg')

guassian = gaussian_lowpass_filter((nature.shape[0],nature.shape[1]),5)

nature_array = []
for i in range(3):
    imageDim0 = GrayImageFFT()
    imageDim0.load_from_array(nature[:,:,i])
    imageDim0.fft()
    imageDim0.apply_filter(guassian)
    nature_array.append(imageDim0.get_filtered_image())

gaussian_nature = np.zeros(nature.shape)
gaussian_nature[:,:,0] = nature_array[0]
gaussian_nature[:,:,1] = nature_array[1]
gaussian_nature[:,:,2] = nature_array[2]
gaussian_nature = (gaussian_nature-gaussian_nature.min())/(gaussian_nature.max()-gaussian_nature.min())

plt.figure(figsize=(12,12))
plt.subplot(2,2,1)
plt.imshow(nature)
plt.subplot(2,2,2)
plt.imshow(gaussian_nature)

plt.imsave(defaultPath+'NatureBlur.jpg',gaussian_nature)

# ### Gaussian Deblur

# In[386]:

nature=plt.imread(defaultPath+'NatureBlur.jpg')

gauss =1/(1e-1+gaussian_lowpass_filter((nature.shape[0],nature.shape[1]),5))

nature_array = []
for i in range(3):
    imageDim0 = GrayImageFFT()
    imageDim0.load_from_array(nature[:,:,i])
    imageDim0.fft()
    imageDim0.apply_filter(guassian)
    nature_array.append(imageDim0.get_filtered_image())

gaussian_nature = np.zeros(nature.shape)
gaussian_nature[:,:,0] = nature_array[0]
gaussian_nature[:,:,1] = nature_array[1]
gaussian_nature[:,:,2] = nature_array[2]
gaussian_nature = (gaussian_nature-gaussian_nature.min())/(gaussian_nature.max()-gaussian_nature.min())

plt.figure(figsize=(12,12))
plt.subplot(1,2,1)
plt.imshow(nature)
plt.subplot(1,2,2)
plt.imshow(gaussian_nature)

plt.imsave(defaultPath+'NatureDeblur.jpg',gaussian_nature)

# ### White Noise or Random Noise

# In[504]:

def random_noise(image,noise_percentage,saltPercent):
    img_noise = np.copy(image)
    noise_num = np.int(np.round(noise_percentage * img_noise.size))
    x=np.random.randint(0,img_noise.shape[0],noise_num)
    y=np.random.randint(0,img_noise.shape[1],noise_num)

    salt_vs_pepper = np.random.binomial(1,saltPercent,size=noise_num)*255
    img_noise[x,y,0] = salt_vs_pepper
    img_noise[x,y,1] = salt_vs_pepper
    img_noise[x,y,2] = salt_vs_pepper
    return img_noise

# In[505]:

def median_filter(data):
    new_image = np.zeros(data.shape)
    for k in range(0,data.shape[2]):
        for i in range(1, data.shape[0]-1):
            for j in range(1, data.shape[1]-1):
                temp = [
                   data[i-1, j-1,k],
                   data[i-1, j,k],
                   data[i-1, j + 1,k],
                   data[i, j-1,k],
                   data[i, j,k],
                   data[i, j + 1,k],
                   data[i + 1, j-1,k],
                   data[i + 1, j,k],
                   data[i + 1, j + 1,k]]
                temp = sorted(temp)
                new_image[i, j,k]= temp[4]
    return new_image

# In[514]:

airplane=plt.imread(defaultPath+'Airplane.jpg')
noisy_image = random_noise(airplane,0.05,1)
denoise_image = median_filter(median_filter(noisy_image))

plt.figure(figsize=(15,15))
plt.subplot(1,2,1)
plt.imshow(noisy_image)
plt.subplot(1,2,2)
plt.imshow(denoise_image/255)

plt.imsave(defaultPath+'Airplane_WhiteNoise.jpg',noisy_image)
plt.imsave(defaultPath+'Airplane_WhiteNoise_Fixed.jpg',denoise_image/255)

# ### Salt And Pepper Noise

# In[515]:

airplane=plt.imread(defaultPath+'Airplane.jpg')
noisy_image = random_noise(airplane,0.05,0.4)
denoise_image = median_filter(median_filter(noisy_image))

plt.figure(figsize=(15,15))
plt.subplot(1,2,1)
plt.imshow(noisy_image)
plt.subplot(1,2,2)
plt.imshow(denoise_image/255)

plt.imsave(defaultPath+'Airplane_SaltPepperNoise.jpg',noisy_image)
plt.imsave(defaultPath+'Airplane_SaltPepperNoise_Fixed.jpg',denoise_image/255)

# ### Histogram Matching

# In[627]:

def histogram_matching(src, image):
    old_shape = src.shape
    source = src.ravel()
    image = image.ravel()

    source_values, index, source_counts = np.unique(src, return_inverse=True,return_counts=True)
    image_values, image_counts = np.unique(image, return_counts=True)

    s_cum = np.cumsum(source_counts).astype(np.float64)
    s_cum /= s_cum[-1]
    t_cum = np.cumsum(image_counts).astype(np.float64)
    t_cum /= t_cum[-1]

    intercept_result = np.interp(s_cum, t_cum, image_values)

    return interp_t_values[index].reshape(oldshape)

# In[628]:

imageref=eyeref=plt.imread(defaultPath+'eyeref.png')
imageref = np.round(color.rgb2gray(imageref)*255)

image2=plt.imread(defaultPath+'eye.png')
image2 = np.round(color.rgb2gray(image2)*255)

matched = hist_match(image2,imageref)

plt.figure(figsize=(15,15))
plt.subplot(1,3,1)
plt.imshow(image2,cmap='gray')
plt.title('Source Image')

plt.subplot(1,3,2)
plt.imshow(imageref,cmap='gray')
plt.title('ReferenceImage')

plt.subplot(1,3,3)
plt.imshow(matched,cmap='gray')
plt.title('FixedImage')

plt.imsave(defaultPath+'EyeHistogram.png',matched)

# In[ ]:

# In[ ]:

# In[ ]:


import math
import pylab
import scipy.optimize
plot = pylab.plot
legend = pylab.legend

def f1(x):
    """ Computes and returns f1(x). """
    return math.cos(2.0 * x * math.pi) * math.exp(- x ** 2)

def f2(x):
    """ Computes and returns f2(x). """
    return math.log(x + 2.2)

def f3(x):
    """ Computes and returns f1(x) - f2(x). """
    return f1(x) - f2(x)

def create_plot_data(f, xmin, xmax, n):
    """
    Computes and returns values of y = f(x).

    f -- function of x
    xmin -- minimum value of x
    xmax -- maximum value of x
    n -- number of values of x

    returns values of x and y
    """
    xs = []
    ys = []
    for i in range(n):
        xi = xmin + float(i) * (xmax - xmin) / (n - 1)
        yi = f(xi)
        xs.append(xi)
        ys.append(yi)
    return (xs, ys)

def myplot():
    """ Plots f1 and f2, displays graph, saves pdf and png, returns None. """
    data1 = create_plot_data(f1, -2, 2, 1001)
    data2 = create_plot_data(f2, -2, 2, 1001)
    plot(data1[0], data1[1], label="f1")
    plot(data2[0], data2[1], label="f2")
    pylab.xlabel("x")
    legend()
    pylab.savefig("plot.png")
    pylab.savefig("plot.pdf")
    return None

def find_cross():
    """ Computes and returns an approximate root of f1(x) - f2(x) = 0 """
    return scipy.optimize.brentq(f3, 0.091, 0.093)


import pandas as pd
import numpy as np

def dcg(relevance_map, pred_order, is_log_decay=True, k=None):
    if k == None:
        k = len(pred_order)
    dcg_score = 0.0
    for i in range(k):
        pred_id = pred_order[i]
        if is_log_decay:
            dcg_score += float(relevance_map.get(pred_id,0.0)) / np.log(i+2)
        else:
            dcg_score += float(relevance_map.get(pred_id,0.0)) * float(k-i) / k
    return dcg_score

def ndcg(relevance_col, prediction_col, is_log_decay=True, k=None, use_random_shuffle=True):
    """Both map should be pandas dataframe column called 'score' with index 'node_id'!"""
    if use_random_shuffle:
        # do random shuffle due to ties in the predicted scores (prediction_order can change between ties)
        prediction_col = prediction_col.sample(frac=1)
    if k == None or (k > len(prediction_col) or k > len(relevance_col)):
        k = min(len(prediction_col),len(relevance_col))
    pred_order = list(prediction_col.sort_values("score",ascending=False).index[:k])
    relevance_order = list(relevance_col.sort_values("score",ascending=False).index[:k])
    relevance_map = dict(relevance_col["score"])
    dcg_val, idcg_val = dcg(relevance_map,pred_order,k=k,is_log_decay=is_log_decay), dcg(relevance_map,relevance_order,k=k,is_log_decay=is_log_decay)
    ndcg_val = 0.0 if idcg_val == 0.0 else float(dcg_val) / idcg_val
    return ndcg_val


import math
import numpy as np
from tqdm import tqdm
from .base import BaseModel

class Perceptron(BaseModel):

    def __init__(self, epochs=1000, learning_rate=0.1, random_seed=1):
        self.weights = None
        self.bias = None
        self.epochs = epochs
        self.learning_rate = learning_rate
        self.seed = random_seed
        self.loss = []

    def _init_weights(self, n_features):
        """Randomly initialize weights and bias. Parameters will be set to random
            values between [-1/sqrt(N), 1/sqrt(N)].

            Args:
                n_features (int): number of input features
        """
        limit = 1 / math.sqrt(n_features)
        random_gen = np.random.RandomState(self.seed)
        # uniform initializations is arbitrary,
        # you may try different ones like normal
        self.weights = random_gen.uniform(-limit, limit, (n_features,))
        self.bias = random_gen.uniform(-limit, limit, (1,))

    def fit(self, X, Y):
        """Fit model on X and Y training data

        Args:
            X (np.array): input, shape (n_samples, n_features)
            Y (np.array): output, shape (n_samples)
        """
        n_features = X.shape[1]
        self._init_weights(n_features)

        for _ in tqdm(range(self.epochs)):
            # feedforward and predict
            output = self._forward(X)

            # compare
            errors = (Y - output)

            # update weight and bias
            gradient_weights = np.dot(errors, X)
            self.weights += self.learning_rate * gradient_weights
            gradient_bias = np.sum(errors)
            self.bias += self.learning_rate * gradient_bias

            self.loss.append(self.sum_squared_error(Y, output))

    def linear(self, Z):
        """Activation function. return Z.
            Very redudant, but here to be
            consistent with the rest of the framework

        Args:
            Z (np.array): shape (n_features)

        Returns:
            (np.array): shape (n_features)
        """
        return Z

    def sum_squared_error(self, actual, predicted):
        """sum of squared error

            sum(error^2)/2

        Args:
            actual (np.array): shape, (n_features)
            predicted (np.array): shape, (n_features)

        Returns:
            float: mse error value
        """
        return np.sum(np.square(actual - predicted)) / 2.0

    def _forward(self, X):
        """returns feedforward prediction

        Args:
            X (np.array): shape (n_samples, n_features)

        Returns:
            (np.array): shape (n_samples)
        """
        # (n_samples, n_features) x (n_features,)
        # feedforward, shape (n_samples,)
        output = np.dot(X, self.weights) + self.bias
        # pass feedforward results to activation function
        output = self.linear(output)
        return output

    def predict(self, X):
        """returns binary classification prediction. using the
            step function.

            1 if X > 0.0
            0 if X < 0.0

        Args:
            X (np.array): shape (n_samples, n_features)

        Returns:
            np.array: shape (n_samples,)
        """
        return np.where(self._forward(X) > 0.0, 1, 0)


from math import sqrt, floor, log

import numpy as np

from numba import jit

@jit(nopython=False, cache=True)
def trial_division_method(limit):
    '''
    Inputs:

    limit -- positive integer, required amount of first consecutive prime numbers

    Returns an integer, the sum of all first prime numbers.
    '''

    founded = 6

    if limit < founded:
        return sum((2, 3, 5, 7, 11, 13)[:limit])

    total = sum((2, 3, 5, 7, 11, 13))

    # Initialize candidate to odd number
    candidate = 13

    while founded < limit:

        # Test only odd numbers
        candidate += 2

        for num in range(3, floor(sqrt(candidate)) + 1, 2):
            if candidate % num is 0:
                break
        else:
            total += candidate
            founded += 1

    return total

@jit(nopython=False, cache=True)
def factor_division_method(limit):
    '''
    Inputs:

    limit
    -- integer, required amount of first consecutive prime numbers
    -- must be greater than or equal to 6

    Returns an integer, the sum of all first prime numbers.
    '''

    # Exploit the fact that every composite number has prime factors
    # that are smaller than the number itself. If the numer does not
    # have prime factors, it must be prime.

    # Leave the only even prime number for the end and focus on odd numbers
    limit -= 1

    founded = 5

    primes = np.zeros(shape=limit, dtype=np.uint32)

    primes[:founded] = (3, 5, 7, 11, 13)

    # Initialize candidate to odd number
    candidate = 13

    while founded < limit:

        # Test only odd numbers
        candidate += 2

        maxnum = floor(sqrt(candidate)) + 1

        for num in primes:
            if candidate % num is 0:
                break
            elif num > maxnum:
                primes[founded] = candidate
                founded += 1
                break

    # Now it is time to include numer two
    return np.sum(primes) + 2

@jit(nopython=False, cache=True)
def ambi_sieve(n):
    '''
    Input:

    n
    -- integer, upper bound of a range
    -- must be greater than or equal to 6

    Returns 1D numpy array of integers, all prime numbers
    between 2 (inclusive) and n (exclusive).

    This algorithm is from https://stackoverflow.com/a/2068548
    and is originally written for Python 2.

    Minor changes to the code were made to adjust it to Python 3.
    '''

    sieve = np.arange(3, n, 2, dtype=np.uint32)

    for m in range(3, floor(sqrt(n)) + 1, 2):
        if sieve[(m - 3) // 2]:
            sieve[(m * m - 3) // 2::m] = 0

    return np.r_[2, sieve[sieve > 0]]

@jit(nopython=False, cache=True)
def primesfrom2to(n):
    '''
    Input:

    n
    -- integer, upper bound of a range
    -- must be greater than or equal to 6

    Returns 1D numpy array of integers, all prime numbers
    between 2 (inclusive) and n (exclusive).

    This algorithm is from https://stackoverflow.com/a/2068548
    and is originally written for Python 2.

    Minor changes to the code were made to adjust it to Python 3.
    '''

    sieve = np.ones(n // 3 + (n % 6 == 2), dtype=np.bool)

    for i in range(1, floor(sqrt(n)) + 1):
        if sieve[i]:
            k = (3 * i + 1) | 1
            sieve[k * k // 3::2 * k] = False
            sieve[k * (k - 2 * (i & 1) + 4) // 3::2 * k] = False

    return np.r_[2, 3, (3 * np.nonzero(sieve)[0][1:] + 1) | 1]

@jit(nopython=True)
def approximate_prime(i, c=0.45):
    '''
    Inputs:

    i
    -- positive integer, i-th prime number
    -- it must be at least 20, when constant is 0.45

    c
    -- float number, constant
    -- must be greater than or equal to 0.0 and less than 1.0 (default is 0.45)
    -- minimum value for argument i depends on this constant

    Returns positive integer, an approximation of the i-th prime number
    that is greater than true i-th prime number.
    '''

    # Makes use of the prime number theorem and the Rosser's
    # theorem to narrow the upper bound.

    a = log(i)

    return floor(i * (a + log(a) - c))

Daftcode Python Level UP 2018 solutions/zadanie2/task2.py


import unittest

import numpy as np
import statsmodels.api as sm

from utils import prepare_data

class TestActivity3_01(unittest.TestCase):
    def setUp(self):
        self.data = prepare_data()

    def test_model(self):
        columns = ["duration", "campaign", "pdays", "cons.price.idx",
                   "cons.conf.idx", "euribor3m"]
        X = self.data[columns]
        X = sm.add_constant(X)
        y = np.where(self.data["y"] == "yes", 1, 0)

        logistic_regression_model = sm.Logit(y, X)
        result = logistic_regression_model.fit()
        params = result.params

        self.assertAlmostEqual(params["const"], -43.137, places=2)
        self.assertAlmostEqual(params["duration"], 0.004, places=2)
        self.assertAlmostEqual(params["campaign"], -0.049, places=2)
        self.assertAlmostEqual(params["pdays"], -0.001, places=2)
        self.assertAlmostEqual(params["cons.price.idx"], 0.492, places=2)
        self.assertAlmostEqual(params["cons.conf.idx"], 0.069, places=2)
        self.assertAlmostEqual(params["euribor3m"], -0.72, places=2)


import numpy as np
from numpy.random import rand
from math import sqrt, log
from timeit import timeit as ti

def dist1(A, B):
    # Preallocate output array.
    # Start with everything set to 0.
    D = np.zeros((A.shape[0], B.shape[0]))
    # For each row in A
    for i in xrange(A.shape[0]):
        # For each row in B
        for j in xrange(B.shape[0]):
            # For corresponding entries of
            # the rows in A and B
            for k in xrange(A.shape[1]):
                # Add the squared difference.
                D[i,j] += (A[i,k] - B[j,k])**2
            # Take square root after finishing sum.
            D[i,j] = sqrt(D[i,j])
    return D

def dist2(A, B):
    # Preallocate output array.
    # This time we'll be overwriting it,
    # so there's no need to assign it values.
    D = np.empty((A.shape[0], B.shape[0]))
    # For each row in A
    for i in xrange(A.shape[0]):
        # For each row in B
        for j in xrange(B.shape[0]):
            # Take the distance between the rows
            D[i,j] = sqrt(((A[i] - B[j])**2).sum())
    return D

def dist3(A, B):
    # Preallocate output array
    D = np.empty((A.shape[0], B.shape[0]))
    # For each row in A
    for i in xrange(A.shape[0]):
        # Take distance from this row to each row in B.
        D[i] = np.sqrt(((A[i] - B)**2).sum(axis=1))
    return D

def dist4(A, B):
    # Use the fact that
    # (a-b)**2 = a**2 + b**2 - 2*a*b
    # Take squares of A and B.
    # Reshape so broadcasting works later
    A2 = (A**2).sum(axis=1).reshape((-1,1))
    B2 = (B**2).sum(axis=1).reshape((1,-1))
    # Use matrix multiplication to start
    # computing the remaining term.
    D = A.dot(B.T)
    # Multiply in place to avoid
    # allocating temporary arrays.
    D *= -2
    # Broadcast to add in A2 and B2.
    # Perform these operations in place.
    D += A2
    D += B2
    # Take square root without
    # allocating a temporary array.
    np.sqrt(D, out=D)
    return D

def time(sizes):
    t1 = []
    t2 = []
    t3 = []
    t4 = []
    for size in sizes:
        A = rand(size, 10)
        B = rand(size, 10)
        t1.append(ti("dist1(A, B)", setup="from __main__ import dist1, A, B", number=10))
        t2.append(ti("dist2(A, B)", setup="from __main__ import dist2, A, B", number=10))
        t3.append(ti("dist3(A, B)", setup="from __main__ import dist3, A, B", number=10))
        t4.append(ti("dist4(A, B)", setup="from __main__ import dist4, A, B", number=10))
        print size
    times = np.empty((5, len(sizes)))
    times[0] = sizes
    times[1] = t1
    times[2] = t2
    times[3] = t3
    times[4] = t4
    np.save("times.npy", times)

if __name__ == __main__:
    time([10, 50, 100, 200, 300, 400, 500, 750, 1000])


import numpy as np

"""
n-dimension grid
"""

def grid2list(grid, n):
    grid = np.array(grid)
    truedim = grid.shape
    l = np.product(truedim[:n])  # length of the list
    list = np.zeros(np.append(l, truedim[n:]))
    grid2list.index = 0

    def iterate(addr):
        if len(addr) == n:
            list[grid2list.index] = grid[tuple(addr)]
            grid2list.index += 1
        else:
            for i in range(len(grid[tuple(addr)])):
                iterate(np.append(addr, i))

    iterate(np.array([]))
    return list

def list2grid(list, dim):
    list = np.array(list)
    dim = np.array(dim)

    if len(list) != np.product(dim):
        raise Exception("Dimension of grid must match the size of the list.")

    grid = np.zeros(np.append(dim, list.shape[1:]))
    list2grid.index = 0

    def iterate(addr):
        if len(addr) == len(dim):
            grid[tuple(addr)] = list[list2grid.index]
            list2grid.index += 1
        else:
            for i in range(len(grid[tuple(addr)])):
                iterate(np.append(addr, i))

    iterate(np.array([]))
    return grid

def makegrid(init, end, dim=None, res=101):
    init = np.array(init)
    end = np.array(end)

    d = len(init)
    if dim == None:
        dim = np.ones(d) * res

    factors = (end - init) / float(res - 1)
    grid = np.zeros(np.append(dim, len(dim)))

    def iterate(addr):
        if len(addr) == len(dim):
            grid[tuple(addr)] = init + addr * factors
        else:
            for i in range(len(grid[tuple(addr)])):
                iterate(np.append(addr, i))

    iterate(np.array([]))
    return grid


# -*- coding: utf-8 -*-
"""
Created on Thu Mar 26 16:37:36 2020

@author: Philipe_Leal
"""

import numpy as np

def correlation_coefficient_pvalue(data1, data2, n_samples):

    corr_coeffs = np.empty(n_samples)
    obtained_corr = np.corrcoef(data1, data2)[0][1]

    for i in range(n_samples):

        data1_shuffled = np.random.permutation(data1)

        corr_coeffs[i] = np.corrcoef(data1_shuffled, data2)[0][1]

    p_value = np.mean( np.abs(corr_coeffs) >= np.abs(obtained_corr) )

    return {'Randomized_Pearson_Mean_Corr' : np.mean(corr_coeffs),
            'IC': np.percentile(corr_coeffs, [2.5, 97.5]),
            'pvalue': p_value}

if '__main__' == __name__:

    """Do a permutation test: Permute the series1 data values but leave the
        series 2 untouched.

       Evaluate the correlation between the permutated and the original data
       for all iterations.

       Evaluate the amount of times (in %)
       that the randomized pvalue got more extreme than the observed one.

       This percentage represents the probability of having a correlation
       more extreme than the observed one given that
       the two series are independent: therefore, have no correlation
       between themselves.

       The IC represents the thresholds that would be expected in case
       both series were independent assuming normal distribution.
       If the given returned correlation coefficient is out of that bound,
       we could assume that the data is not independent.

    """

    data1 = np.random.normal(-50,4, 100)

    data2 = np.random.normal(15, 1, 100)
    n_samples = 9999

    R = correlation_coefficient_pvalue(data1, data2, n_samples)

    print(R)


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

from numpy import linspace, zeros, exp
import matplotlib.pyplot as plt

N_0 = int(input('Give initial population size N_0: '))
r   = float(input('Give net growth rate r: '))
dt  = float(input('Give time step size: '))
N_t = int(input('Give number of steps: '))
t = linspace(0, N_t*dt, N_t+1)
N = zeros(N_t+1)

N[0] = N_0
for n in range(N_t):
    N[n+1] = N[n] + r*dt*N[n]

numerical_sol = 'bo' if N_t < 70 else 'b-'
plt.plot(t, N, numerical_sol, t, N_0*exp(r*t), 'r-')
plt.legend(['numerical', 'exact'], loc='upper left')
plt.xlabel('t')
plt.ylabel('N(t)')
filestem = 'growth1_%dsteps' % N_t
plt.savefig('%s.png' % filestem)
plt.savefig('%s.pdf' % filestem)


# File: linear.py
# Last Change: 29.10.2018
# Content: Linear Regression layout class
# Authors: Jonas Weimar,

import numpy as np

# => Simple Linear Regression Model
class SLRModel(object):

    # Initializer / Constructor:
    def __init__(self):
        self.coef = []

    # Hook methods for build in functions:
    def __str__(self):
        return "f(x) = {}x + {}".format(self.coef[0], self.coef[1])

    def __getitem__(self, key):
        return self.coef[key]

    # Public Methods
    def fit(self, x, y):
        self.coef.clear()

        n = np.size(x)
        x_mean, y_mean = np.mean(x), np.mean(y)

        ss_xy, ss_xx = np.sum(y*x - n*y_mean*x_mean), np.sum(x*x - n*x_mean*x_mean)

        m = ss_xy / ss_xx
        b = y_mean - m*x_mean

        self.coef = [m, b]

    def predict(self, x):
        result = []
        for row in x:
            result.append( (self.coef[0] * row + self.coef[1]) )
        return result