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

#
# メルフィルタバンクを作成してプロットします．
#

# 数値演算用モジュール(numpy)をインポート
import numpy as np

# プロット用モジュール(matplotlib)をインポート
import matplotlib.pyplot as plt

#
# 周波数をヘルツからメルに変換する
#
def Herz2Mel(herz):
    return (1127.0 * np.log(1.0 + herz / 700))

#
# メイン関数
#
if __name__ == "__main__":

    # 最大周波数 [Hz]
    max_herz = 8000

    # FFTのポイント数
    fft_size = 4096

    # フィルタバンクの数
    num_mel_bins = 7

    # プロットを出力するファイル(pngファイル)
    out_plot = './mel_bank.png'

    # メル軸での最大周波数
    max_mel = Herz2Mel(max_herz)

    # メル軸上での等間隔な周波数を得る
    mel_points = np.linspace(0, max_mel, num_mel_bins+2)

    # パワースペクトルの次元数 = FFTサイズ/2+1
    dim_spectrum = int(fft_size / 2) + 1

    # メルフィルタバンク(フィルタの数 x スペクトルの次元数)
    mel_filter_bank = np.zeros((num_mel_bins, dim_spectrum))
    for m in range(num_mel_bins):
        # 三角フィルタの左端，中央，右端のメル周波数
        left_mel = mel_points[m]
        center_mel = mel_points[m+1]
        right_mel = mel_points[m+2]
        # パワースペクトルの各ビンに対応する重みを計算する
        for n in range(dim_spectrum):
            # 各ビンに対応するヘルツ軸周波数を計算
            freq = 1.0 * n * max_herz / dim_spectrum
            # メル周波数に変換
            mel = Herz2Mel(freq)
            # そのビンが三角フィルタの範囲に入っていれば，重みを計算
            if mel > left_mel and mel < right_mel:
                if mel <= center_mel:
                    weight = (mel - left_mel) / (center_mel - left_mel)
                else:
                    weight = (right_mel-mel) / (right_mel-center_mel)
                mel_filter_bank[m][n] = weight

    # プロットの描画領域を作成
    plt.figure(figsize=(6,4))

    # 横軸(周波数軸)を作成する
    freq_axis = np.arange(dim_spectrum) \
                * max_herz / dim_spectrum

    for m in range(num_mel_bins):
        # フィルタバンクをプロット
        plt.plot(freq_axis, mel_filter_bank[m], color='k')
        #plt.plot(freq_axis, mel_filter_bank[m])

    plt.xlabel('Frequency [Hz]')

    # 横軸の表示領域を0～最大周波数に制限
    plt.xlim([0, max_herz])

    # プロットを保存する
    plt.savefig(out_plot)


'''
  Computes the spatial median based on (real or complex) data matrix X.
  INPUT:
         X: Numeric data matrix of size N x p. Each row represents one
           observation, and each column represents one variable
 printitn : print iteration number (default = 0, no printing)

 OUTPUT
      smed: Spatial median estimate
'''

import numpy as np

def spatmed(X,printitn=0,iterMAX = 500,EPS=1e-6,TOL=1e-5):
    l = np.sum(X*np.conj(X),axis=1)
    X = X[l!=0,:]
    n = len(X)

    smed0 = np.median(X) if np.isrealobj(X) else np.mean(X)
    norm0 = np.linalg.norm(smed0)

    for it in range(iterMAX):
        Xc = X - smed0
        l = np.sqrt(np.sum(Xc*np.conj(Xc),axis=1))
        l[l<EPS] = EPS
        Xpsi = Xc / l
        update = np.sum(Xpsi,axis=0)/sum(1/l)
        smed = smed0 + update

        dis = np.linalg.norm(update,ord=2)/norm0

        if printitn>0 and (i+1) % printitn == 0: print('At iter = %.3d, dis =%.7f \n' % (i,dis))

        if dis <= TOL: break
        smed0 = smed
        norm0 = np.linalg.norm(smed,ord=2)
    return smed


# some explanation
# when some assumptions are not true -- data is small and
# variance is different, we use nonparametric statistics
# it is useful to detect preference in data
# chi_square test is one of the method

import numpy as np

def chi_square(X):
    """
                (O - E)^2
    X^2 = sum  -----------
                    E
    """
    n = X.shape[0]
    E = np.sum(X) / n
    chi_2 = sum((X - E) ** 2 / E)
    return chi_2

if __name__ == '__main__':
    X = np.array([23, 17, 50])
    chi_2 = chi_square(X)
    print('Chi square is: {}'.format(chi_2))
    # another table lookup


#The Hacker Within: Python Boot Camp 2010 - Session 07 - Using SciPy.
#Presented by Anthony Scopatz.
#
#SciPy special functions, walk before you run!

#Code that numerically approximates common (and some not-so-common) special functions can be found in 'scipy.special'
from scipy.special import *

#Here you can find things like error functions, gamma functions, Legendre polynomials, etc.
#But as a example let's focus on my favorites: Bessel functions.
#Time for some graphs...
from pylab import *

x = arange(0.0, 10.1, 0.1)

for n in range(4):
	j = jn(n, x)
	plot(x, j, 'k-')
	text(x[10*(n+1)+1], j[10*(n+1)], r'$J_%r$'%n)

for n in range(3):
	y = yn(n, x)
	plot(x, y, 'k--')
	text(x[10*(n)+6], y[10*(n)+5], r'$Y_%r$'%n)

axis([0, 10, -2, 1.25])
xlabel(r'$x$')
ylabel("Bessel Functions")

show()

#Check out http://docs.scipy.org/doc/scipy/reference/special.html for a complete listing.

#Note that the figure that was created here is a reproduction of
#Figure 6.5.1 in 'Numerical Recipes' by W. H. Press, et al.


import math
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.io import loadmat
import scipy.optimize as opt

data = loadmat('data/ex3data1.mat')

def g(z):
	#sigmoid function
	return 1.0 / (1 + math.pow(math.e, -z))

g = np.vectorize(g, otypes=[np.float64])
#now, when g is applied to a vector, it is applied to each cell

def J_Reg(theta, x, y, lamda):
	#using the vector notation
	ones = np.ones((y.shape[0],), dtype=np.float64)
	h = g(x @ theta)
	tmp = y.transpose() @ np.log(h) + (ones - y).transpose() @ np.log(ones - h)
	reg_term = lamda / (2 * x.shape[0]) * (theta[1:].transpose() @ theta[1:])
	j = -(tmp) / x.shape[0] + reg_term
	return j

def gradientReg(theta, x, y, lamda):
	tmp = x.transpose() @ (g(x @ theta) - y)
	reg_term = (lamda / x.shape[0]) * theta
	reg_term[0] = 0
	grad = tmp + reg_term
	return grad

def getClassifiers():
	global x, y
	lamda = 1
	#theta contains 10 classifiers, where theta[i] is the ith classifier
	theta = np.zeros((10, x.shape[1]), dtype=np.float64)
	for i in range(10):
		y_i = np.array([1 if elem == i else 0 for elem in y])
		fmin = opt.minimize(fun=J_Reg, x0=theta[i], args=(x, y_i, lamda), method='TNC', jac=gradientReg)
		theta[i] = fmin.x
	return theta

def findAccuracy(theta, x, y):
	predictor = x @ theta.transpose()
	predicted = np.argmax(predictor, axis=1)
	diff = predicted - y
	correct = 0
	for elem in diff:
		if (elem == 0):
			correct += 1
	accuracy = correct / y.shape[0]
	return accuracy

tmp = np.ones(((data['X'].shape)[0],1), dtype=np.float64)
x = np.insert(data['X'], [0], tmp, axis=1)
y_prime = data['y'].transpose()[0]
y = np.array([elem if elem != 10 else 0 for elem in y_prime])

theta = getClassifiers()
print(findAccuracy(theta, x, y))


import numpy as np
import math
from scipy.stats import norm
import cv2

# we choose our dimensions in such a way that this can be easily
# viewed when using python's default print statement
# This returns a tensor of the h+1 basis filters
# for rotationally symmetric filters
# TODO: do we want to padd with more zeros? I think we're fine, but maybe worth asking
def createBasisWeights(h):
  w = np.zeros((h+1, 2*h+1, 2*h+1))

  for n in range(h+1):
    for x in range(-h, h+1):
      for y in range(-h, h+1):
        r = np.sqrt(x**2 + y**2)
        if r > n-1 and r < n:
          w[n,x+h, y+h] = (r - (n-1)) / (n + 1)
        if r >= n and r < n+1:
          w[n,x+h, y+h] = ((n+1) - r) / (n + 1)
  return w

def createBasisWeightsGaussian(h, sigma):
  w = np.zeros((h+1, 2*h+1, 2*h+1))

  for n in range(h+1):
    for x in range(-h, h+1):
      for y in range(-h, h+1):
        r = np.sqrt(x**2 + y**2)
        w[n,x+h, y+h] = norm.pdf(r, n, sigma)
  return w

def createBasisWeightsDiameter(d):
  h = math.floor(d/2)
  w = np.zeros((math.ceil(d/2), d, d))

  for n in range(math.ceil(d/2)):
    for x in range(math.ceil(-d/2), math.ceil(d/2)):
      for y in range(math.ceil(-d/2), math.ceil(d/2)):
        r = np.sqrt(x**2 + y**2)
        if r > n-1 and r < n:
          w[n,x+h, y+h] = r - (n-1)
        if r >= n and r < n+1:
          w[n,x+h, y+h] = (n+1) - r
  return w

def createBasisWeightsDiameterGaussian(d, sigma):
  w = np.zeros((math.ceil(d/2), d, d))
  c = (d-1)/2

  for n in range(math.ceil(d/2)):
    for x in range(0, d):
      for y in range(0, d):
        r = np.sqrt((x-c)**2 + (y-c)**2)
        w[n,x, y] = norm.pdf(r, n, sigma)
  return w

if __name__=='__main__':
  # make sure our function looks right
  #w = createBasisWeightsGaussian(10)
  #print(w)

  #print(w -np.transpose(w,(0,2,1)))

  # make sure we know how to use tensordot to create a linear combination of our filters
  #p = np.ones((3,))
  #comb = np.tensordot(w, p, [0,0])
  #print(comb)
  # looks correct to me!

  basis = np.reshape(createBasisWeightsGaussian(10,1)[5,:,:],(21,21))
  angle = 45
  cols = 21
  rows = 21
  M = cv2.getRotationMatrix2D((cols/2 - 0.5,rows/2 - 0.5),angle,1)
  Minv = cv2.getRotationMatrix2D((cols/2 - 0.5,rows/2 - 0.5),-angle,1)

  rotimg = cv2.warpAffine(basis,M,(21,21))
  cv2.imshow("basis", basis)
  cv2.imshow("rotbasis",rotimg)
  cv2.imshow("rotdiff", (basis - rotimg))
  cv2.imwrite("../writeup/basis.png", basis*255)
  cv2.imwrite("../writeup/rotbasis45.png", rotimg*255)
  cv2.imwrite("../writeup/diffbasisrot45.png", (basis-rotimg)*255)

  cv2.waitKey(0)
  cv2.destroyAllWindows()


from scipy.special import expit
import numpy as np
import matplotlib.pyplot as plt

def sigmoid(z):
    # SIGMOID Compute sigmoid functoon
    # J = SIGMOID(z) computes the sigmoid of z.
    g = np.zeros(z.shape)
    g = expit(z)

    return g

def costFunction(theta, X, y, return_grad=False):
    # COSTFUNCTION Compute cost and gradient for logistic regression
    #   J = COSTFUNCTION(theta, X, y) computes the cost of using theta as the
    #   parameter for logistic regression and the gradient of the cost
    #   w.r.t. to the parameters.
    # Initialize some useful values
    m = len(y) # number of training examples
    J = 0
    grad = np.zeros(theta.shape)
    one = y * np.transpose(np.log(sigmoid(np.dot(X, theta))))
    two = (1 - y) * np.transpose(np.log(1 - sigmoid(np.dot(X, theta))))
    J = -(1. / m) * (one + two).sum()
    grad = (1. / m) * np.dot(sigmoid(np.dot(X, theta)).T - y, X).T

    if return_grad == True:
        return J, np.transpose(grad)
    elif return_grad == False:
        return J

def predict(theta, X):
    # PREDICT Predict whether the label is 0 or 1 using learned logistic
    # regression parameters theta
    #   p = PREDICT(theta, X) computes the predictions for X using a
    #   threshold at 0.5 (i.e., if sigmoid(theta'*x) >= 0.5, predict 1)
    m = X.shape[0] # Number of training examples
    p = np.zeros((m, 1))
    sigValue = sigmoid(np.dot(X,theta))
    p = sigValue >= 0.5

    return p

def plotData(X, y):
    # PLOTDATA Plots the data points X and y into a new figure
    #   PLOTDATA(x,y) plots the data points with + for the positive examples
    #   and o for the negative examples. X is assumed to be a Mx2 matrix.
    # Find Indices of Positive and Negative Examples
    pos = np.where(y==1)
    neg = np.where(y==0)
    p1 = plt.plot(X[pos,0], X[pos,1], marker='+', markersize=9, color='k')[0]
    p2 = plt.plot(X[neg,0], X[neg,1], marker='o', markersize=7, color='y')[0]

    return plt, p1, p2

def mapFeature(X1, X2):
    #   MAPFEATURE(X1, X2) maps the two input features
    #   to quadratic features used in the regularization exercise.
    #
    #   Returns a new feature array with more features, comprising of
    #   X1, X2, X1.^2, X2.^2, X1*X2, X1*X2.^2, etc..
    #   for a total of 1 + 2 + ... + (degree+1) = ((degree+1) * (degree+2)) / 2 columns
    #
    #   Inputs X1, X2 must be the same size
    degree = 6
    out = np.ones(( X1.shape[0], sum(range(degree + 2)) ))
    curr_column = 1
    for i in range(1, degree + 1):
        for j in range(i+1):
            out[:, curr_column] = np.power(X1, i-j) * np.power(X2, j)
            curr_column += 1

    return out

def plotDecisionBoundary(theta, X, y):
    #   PLOTDECISIONBOUNDARY(theta, X,y) plots the data points with + for the
    #   positive examples and o for the negative examples. X is assumed to be
    #   a either
    #   1) Mx3 matrix, where the first column is an all-ones column for the
    #      intercept.
    #   2) MxN, N>3 matrix, where the first column is all-ones
    fig = plt.figure()
    fig, p1, p2 = plotData(X[:, 1:3], y)
    fig.hold(True)

    if X.shape[1] <= 3:
        # Only need 2 points to define a line, so choose two endpoints
        plot_x = np.array([min(X[:, 1]) - 2, max(X[:, 1]) + 2])
        # Calculate the decision boundary line
        plot_y = (-1. / theta[2]) * (theta[1] * plot_x + theta[0])
        # Plot, and adjust axes for better viewing
        p3 = fig.plot(plot_x, plot_y)
        # Legend, specific for the exercise
        fig.legend((p1, p2, p3[0]), ('Admitted', 'Not Admitted', 'Decision Boundary'), numpoints=1, handlelength=0.5)
        fig.axis([30, 100, 30, 100])
        fig.show(block=False)
    else:
        # Here is the grid range
        u = np.linspace(-1, 1.5, 50)
        v = np.linspace(-1, 1.5, 50)
        z = np.zeros((len(u), len(v)))
        # Evaluate z = theta*x over the grid
        for i in range(len(u)):
            for j in range(len(v)):
                z[i, j] = np.dot(mapFeature(np.array([u[i]]), np.array([v[j]])), theta)
        z = np.transpose(z)  # important to transpose z before calling contour
        # Notice you need to specify the level 0
        # we get collections[0] so that we can display a legend properly
        p3 = fig.contour(u, v, z, levels=[0], linewidth=2).collections[0]
        # Legend, specific for the exercise
        fig.legend((p1, p2, p3), ('y = 1', 'y = 0', 'Decision Boundary'), numpoints=1, handlelength=0)
        fig.show(block=False)

    fig.hold(False)  # prevents further drawing on plot

def costFunctionReg(theta, X, y, lambda_reg, return_grad=False):
    #   J = COSTFUNCTIONREG(theta, X, y, lambda) computes the cost of using
    #   theta as the parameter for regularized logistic regression and the
    #   gradient of the cost w.r.t. to the parameters.
    # Initialize some useful values
    m = len(y) # number of training examples
    J = 0
    grad = np.zeros(theta.shape)
    one = y * np.transpose(np.log(sigmoid( np.dot(X,theta))))
    two = (1 - y) * np.transpose(np.log(1 - sigmoid( np.dot(X,theta))))
    reg = (float(lambda_reg) / (2 * m)) * np.power(theta[1:theta.shape[0]], 2).sum()
    J = -(1. / m)*(one + two).sum() + reg
    # applies to j = 1,2,...,n - NOT to j = 0
    grad = (1. / m) * np.dot(sigmoid(np.dot(X, theta) ).T - y, X).T + (float(lambda_reg) / m)*theta
    # the case of j = 0 (recall that grad is a n+1 vector)
    # since we already have the whole vectorized version, we use that
    grad_no_regularization = (1. / m) * np.dot(sigmoid( np.dot(X, theta)).T - y, X).T
    # and then assign only the first element of grad_no_regularization to grad
    grad[0] = grad_no_regularization[0]

    if return_grad == True:
        return J, grad.flatten()
    elif return_grad == False:
        return J


import numpy as np

a = np.array([1, 2])

b = np.array([2, 1])

#naive dot product

# dot = 0
#
# for e,f in zip(a,b): # zip groups and packs into 1 single list
#     dot += e*f

dot = a*b  # multiplies element wise so cant be done with different sizes
print(dot)

#now to get dot product from above implementation sum all the terms in dot

print(np.sum(dot)) # sum method is an instance method of the numpy array
                   # itself
#so alternatively
print(dot.sum())

#though both the above methods give the answer , more convenient way to
#calculate the dot product

print(np.dot(a,b))

#like the sum function, the dot function is also an instance method

print(a.dot(b)) # so we can directly call on the array object itself

#or
print(b.dot(a))

## Calculate the angle between a and b using alternate definition of
## dot product

result = a.dot(b) / (np.sqrt((a**2).sum()) * np.sqrt((b**2).sum()))

print(result)
angle = np.arccos(result) # angle between the vectors default in radians

print(angle)

# alternatively we can find it by using

result = a.dot(b) / (np.linalg.norm(a) * np.linalg.norm(b))

print(result)

print(np.arccos(result))


from __future__ import annotations
from typing import Optional, List, Tuple
from logging import Logger, getLogger

from numpy import ndarray, vstack, array, stack
from numpy.linalg import eig, inv, solve

from optmlstat.functions.function_base import FunctionBase

logger: Logger = getLogger()

class QuadraticFunction(FunctionBase):
    """
    Quadratic function. The ith function is

      :math:`f_i(x) = x^T P x + q^T x + r`

    where x is n-dimensional real column-vector, P is an real n-by-n matrix, q is an real n-dimensional
    column vector, and r is a real scalar. i goes from 1 to m.

    Note that when data are actually interchanged, e.g., though method, QuadraticFunction.get_y_array_2d,
    x is represented by row vectors (not column vectors).
    """

    @staticmethod
    def test_convexity(quad_array_3d: ndarray) -> Tuple[bool, bool]:
        is_strictly_convex: bool = True
        is_convex: bool = True
        for idx3 in range(quad_array_3d.shape[2]):
            symmetric_array: ndarray = quad_array_3d[:, :, idx3] + quad_array_3d[:, :, idx3].T
            eigen_value_array: ndarray = eig(symmetric_array)[0]
            if (eigen_value_array <= 0.0).any():
                is_strictly_convex = False

            if (eigen_value_array < 0.0).any():
                is_convex = False

        return is_convex, is_strictly_convex

    def __init__(self, quad_array_3d: Optional[ndarray], slope_array_2d: ndarray, intercept_array_1d: ndarray) -> None:
        """
        If n is the number of inputs and m is that of outputs, quad_array_3d[:, :, i], slope_array_2d[:, i] and
        intercept_array_1d[i] represents :math:`P`, :math:`q`, and :math:`r` respectively in the following equation:

          :math:`f_i(x) = x^T P x + q^T x + r`

        Parameters
        ----------
        quad_array_3d:
         n-by-n-by-m ndarray
        slope_array_2d:
         n-by-m ndarray
        intercept_array_1d: m
         m ndarray
        """
        # check dimensions
        assert quad_array_3d is None or quad_array_3d.ndim == 3, quad_array_3d.ndim
        assert slope_array_2d.ndim == 2, slope_array_2d.ndim
        assert intercept_array_1d.ndim == 1, intercept_array_1d.ndim

        # check number of inputs
        assert quad_array_3d is None or quad_array_3d.shape[0] == slope_array_2d.shape[0]
        assert quad_array_3d is None or quad_array_3d.shape[1] == slope_array_2d.shape[0]

        # check number of outputs
        assert slope_array_2d.shape[1] == intercept_array_1d.size, (slope_array_2d.shape, intercept_array_1d.shape)
        assert quad_array_3d is None or quad_array_3d.shape[2] == intercept_array_1d.size, (
            slope_array_2d.shape,
            intercept_array_1d.shape,
        )

        self.quad_array_3d: ndarray = None if quad_array_3d is None else quad_array_3d.copy()
        self.slope_array_2d: ndarray = slope_array_2d.copy()
        self.intercept_array_1d: ndarray = intercept_array_1d.copy()

        self._is_affine: bool = (self.quad_array_3d == 0.0).all()
        self._is_convex: bool
        self._is_strictly_convex: bool
        self._is_concave: bool
        self._is_strictly_concave: bool

        self._is_convex, self._is_strictly_convex = QuadraticFunction.test_convexity(self.quad_array_3d)
        self._is_concave, self._is_strictly_concave = QuadraticFunction.test_convexity(-self.quad_array_3d)

    @property
    def num_inputs(self) -> Optional[int]:
        return self.slope_array_2d.shape[0]

    @property
    def num_outputs(self) -> Optional[int]:
        return self.slope_array_2d.shape[1]

    @property
    def is_affine(self) -> Optional[bool]:
        return self._is_affine

    @property
    def is_convex(self) -> Optional[bool]:
        return self._is_convex

    @property
    def is_strictly_convex(self) -> Optional[bool]:
        return self._is_strictly_convex

    @property
    def is_concave(self) -> Optional[bool]:
        return self._is_concave

    @property
    def is_strictly_concave(self) -> Optional[bool]:
        return self._is_strictly_concave

    @property
    def conjugate(self) -> QuadraticFunction:
        """
        If the (quadratic) function is not convex, this value can be infinity. (not always though)
        If the function is convex, but not strictly convex, the conjugate is bounded,
         but the calculation is a bit complicated.
        For now, we implement this function only when the function is strictly convex.

        In this case, when :math:`f(x) = x^T P x + q^T x + r`,
        the conjugate is :math:`(z^T P^{-1} z - 2 q^T P^{-1} z + q^T P^{-1} q)/4 - r`.
        """
        assert self.is_strictly_convex

        conjugate_quad_array_3d: ndarray = ndarray(shape=self.quad_array_3d.shape, dtype=float)
        conjugate_slope_array_1d_list: List[ndarray] = list()
        conjugate_intercept_list: List[float] = list()

        for idx in range(self.quad_array_3d.shape[2]):
            p_array_2d: ndarray = self.quad_array_3d[:, :, idx]
            conjugate_quad_array_3d[:, :, idx] = 0.25 * inv(p_array_2d)

            q_array_1d: ndarray = self.slope_array_2d[:, idx]
            p_inv_q_array_1d: ndarray = solve(p_array_2d, q_array_1d)
            conjugate_slope_array_1d_list.append(-0.5 * p_inv_q_array_1d)

            conjugate_intercept_list.append(0.25 * q_array_1d.dot(p_inv_q_array_1d))

        conjugate_slope_array_2d: ndarray = vstack(conjugate_slope_array_1d_list).T
        conjugate_intercept_array_1d: ndarray = array(conjugate_intercept_list, float) - self.intercept_array_1d

        logger.debug(f"conjugate_slope_array_1d_list: {conjugate_slope_array_1d_list}")
        logger.debug(f"conjugate_slope_array_2d.shape: {conjugate_slope_array_2d.shape}")

        return QuadraticFunction(conjugate_quad_array_3d, conjugate_slope_array_2d, conjugate_intercept_array_1d)

    def conjugate_arg(self, z_array_2d: ndarray) -> ndarray:
        """
        The gradient of :math:`z^T x - f(x) = z^T x - x^T P x - q^T x - r` is

          :math:`z - 2 P x - q`

        hence, the argsup is can be obtained when x makes the gradient zero (when P is positive definite), which is

          :math:`(1/2) P^{-1} (z-q)`
        """
        assert self.is_strictly_convex
        assert self.num_inputs is None or z_array_2d.shape[1] == self.num_inputs

        x_array_2d_list: List[ndarray] = list()

        for idx3 in range(self.quad_array_3d.shape[2]):
            p_array_2d: ndarray = self.quad_array_3d[:, :, idx3]
            q_array_1d: ndarray = self.slope_array_2d[:, idx3]

            assert z_array_2d.shape[1] == q_array_1d.size

            x_array_2d: ndarray = solve(p_array_2d, (z_array_2d - q_array_1d).T).T / 2.0

            assert x_array_2d.shape == z_array_2d.shape

            x_array_2d_list.append(x_array_2d)

        x_array_3d: ndarray = stack(x_array_2d_list, axis=2)

        assert x_array_3d.shape == (z_array_2d.shape[0], self.num_inputs, self.num_outputs)

        return x_array_3d

    # TODO (2) check x_array_2d and y_array_2 in all get_y_values_2d methods using decorators

    def get_y_values_2d(self, x_array_2d: ndarray) -> ndarray:
        logger.debug(x_array_2d.shape)
        logger.debug(self.slope_array_2d.shape)
        logger.debug(self.intercept_array_1d.shape)
        y_array_2d = x_array_2d.dot(self.slope_array_2d) + self.intercept_array_1d

        if self.quad_array_3d is not None:
            for idx in range(self.quad_array_3d.shape[2]):
                y_array_2d[:, idx] += (x_array_2d.dot(self.quad_array_3d[:, :, idx]) * x_array_2d).sum(axis=1)

        return y_array_2d


import numpy as np
#sudoku = input("Enter Soduku")
#sudoku= 070000009510420600080300700008001370023080040400900100962800030000010400700203096

#puz = [[int(sudoku[(i+j)-1]) for i in range(1,10)] for j in range(0,81,9)]
unsolved = np.array(
    [3, 9, 6,1, 8, 0, 7, 1, 5, 0, 0, 7, 9, 6, 1, 0, 0, 3, 8, 4, 1, 0, 3, 0, 2, 0, 0, 6, 3, 0, 1, 0, 0, 5, 2, 0, 1, 0,
     0, 7, 2, 5, 3, 9, 0, 0, 5, 2, 6, 9, 3, 8, 0, 1, 4, 0, 8, 3, 7, 6, 0, 0, 2, 2, 0, 5, 8, 0, 9, 0, 3, 4, 9, 6, 3, 0,
     0, 2, 0, 7, 8])

puz=np.reshape(unsolved, (9, 9))

def check(puzzle, i, row, col):
    rows = puzzle[int(row)]
    column = [puzzle[r][col] for r in range(0,9,1)]
    if i in rows:
        return False
    if i in column:
        return False
    SquareRow = (row // 3)*3
    squareColumn = (col // 3)*3
    Square = [puzzle[y][z] for y in range(SquareRow, SquareRow+3) for z in range(squareColumn, squareColumn+3)]
    if i in Square:
        return False
    return True

def find(puzzle):
    for i in range(0,9,1):
        for j in range(0,9,1):
            if puzzle[i][j]==0:
                return i,j
    return None

def solve(board):
    finds = find(board)
    if not finds:
        return True
    else:
        row, col = finds

    for i in range(1,10):
        if check(board, i, row, col):
            board[row][col] = i

            if solve(board):
                return True

            board[row][col] = 0

    return False

print(solve(puz))
print(puz)


import numpy as np

def heaviside(x):
    return x * float(x >= 0.0)

def relu(x):
    x[x < 0] = 0.0
    return x

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

def tanh(x):
    return (np.exp(2*x) - 1) / (np.exp(2*x) + 1)

def softmax(x, tau=1):
    return np.exp(x/tau) / np.sum(np.exp(x/tau))


# this is the fourth order section
# refer to:
# http://mathworld.wolfram.com/Runge-KuttaMethod.html
# https://www.uni-muenster.de/imperia/md/content/physik_tp/lectures/ss2016/num_methods_ii/rkm.pdf

# numpy for mathematical operations and working with states
import numpy as np

def rk4_stp(func, y_n, t_step, t_n):
	# this is the single step rk4 method

	# rename some stuff
	h = t_step
	a21 = .5
	a32 = .5
	a43 = 1.0
	b1 = float(1/6)
	b2 = float(1/3)
	b3 = float(1/3)
	b4 = float(1/6)
	c2 = .5
	c3 = .5
	c4 = 1

	# determine the stage components
	k1 = func(t_n, y_n)
	k2 = func(t_n + c2*h, y_n + h*(a21*k1))
	k3 = func(t_n + c3*h, y_n + h*(a32*k2))
	k4 = func(t_n + c4*h, y_n + h*(a43*k3))

	# perform the step
	y_np1 = y_n + h*(b1*k1 + b2*k2 + b3*k3 + b4*k4)

	# return the next step
	return y_np1

def rk4_mul(func, y_n, t_step, t_span, record = True):
	# this is a multi step rk4 method

	# rename things
	h = t_step
	y_i = y_n

	# create a set of the times
	t_set = np.linspace(t_span[0], t_span[1], (t_span[1]-t_span[0])/t_step)
	y_out = np.reshape(y_n, (6,1)) # maybe make this zeroes? then cut it off later
    # just need to make sure everything lines up, and right now I think it
    # is one time step off hmmm

	# iterate through the time set
	for t in t_set:
		y_i = rk4_stp(func, y_i, t_step, t)
		y_j = np.reshape(y_i, (6,1))
		y_out = np.append(y_out, y_j, axis=1)

	# return the new state
	# if (~record):
		# y_out = y_i
	return y_out


import numpy as np
from scipy.optimize import minimize
from scipy.io import loadmat
from numpy.linalg import det, inv
from math import sqrt, pi, pow
import scipy.io
import matplotlib.pyplot as plt
import pickle
import sys

# The mean matrix is a 2 * 5 matrix
# The entry on column 0 are the mean values of X where trueLabel == 1
# e.g. means[0][0] = mean of all entries in X where along column 0, and trueLabel == 1
# means[1][0] == mean of all entries in X where along column 1, and trueLabel == 1
def findMeanByClass(X,y,k):
	means = np.zeros([X.shape[1],k], dtype=float)
	for i in range(1,k+1):
		row_num_with_i = np.where(y==i)[0] #all the rows from y where the value == i
		trainMatrix    = X[row_num_with_i,:] # all the rows from X where the true label of the entry == i
		#print "trainMatrix :",trainMatrix
		means[:,i-1]   = np.mean(trainMatrix,axis=0).transpose() #axis=0 means along vertical axis,

		#print "means :",means[:,i-1]
	return means

#Same logic as findMeanByClass, we return an additional list of covariance matrix for each mean we find
#Used in QDA analysis
def findMeanByClassWithCovar(X,y,k):
	means = np.zeros([X.shape[1],k], dtype=float)
	covarList = []
	for i in range(1,k+1):
		row_num_with_i = np.where(y==i)[0] #all the rows from y where the value == i
		trainMatrix    = X[row_num_with_i,:] # all the rows from X where the true label of the entry == i
		#print "trainMatrix :",trainMatrix
		means[:,i-1]   = np.mean(trainMatrix,axis=0).transpose() #axis=0 means along vertical axis,
		covarList.append(np.cov(np.transpose(trainMatrix)))
		#print "means :",means[:,i-1]
	return means,covarList

def findClassesInY(y):
	k = np.unique(y)
	return k,len(k)

""""
Generates the predicted label from the p(x) formula
Refer eqn 3.1 in slide B.3 for formula
"""
def getPredictedLabel(testX_transpose,means,invCov,numClass,constantTerm):
	prediction = 0
	pdf = 0.0
	res = 0.0
	pdfList = []
	for j in range(numClass): #for all columns in means matrix
		row = testX_transpose - means[:,j]
		res = constantTerm * np.exp((-1/2) * np.dot( np.dot( np.transpose(row) , invCov)  ,row))
		pdfList.append(res)
	prediction = pdfList.index(max(pdfList)) + 1
	return prediction

""""
Generates the predicted label from the p(x) formula
Refer eqn 3.1 in slide B.3 for formula
"""
def getPredictedLabelForQDA(testX_transpose,means,invCov,numClass,constantTerm):
	prediction = 0
	pdf = 0.0
	res = 0.0
	pdfList = []
	for j in range(numClass): #for all columns in means matrix
		row = testX_transpose - means[:,j]
		res = constantTerm[j] * np.exp((-1/2) * np.dot( np.dot( np.transpose(row) , invCov[j])  ,row))
		pdfList.append(res)
	prediction = pdfList.index(max(pdfList)) + 1
	return prediction

"""%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"""
#
def ldaLearn(X,y):
	#print X
	# print X.shape
	# print y.shape
	N = X.shape[0] #number of elements
	d = X.shape[1] #number of attributes
	uniqueArray,k = findClassesInY(y); #number of classes
    # Inputs
    # X - a N x d matrix with each row corresponding to a training example
    # y - a N x 1 column vector indicating the labels for each training example
    #
    # Outputs
    # means - A d x k matrix containing learnt means for each of the k classes
    # covmat - A single d x d learnt covariance matrix

    # IMPLEMENT THIS METHOD
	means = np.zeros([d,k], dtype=float) # 2*5 matrix
	covmat= np.array([d,d], dtype=float) #2*2 matrix

	means = findMeanByClass(X,y,k)
	covmat = np.cov(np.transpose(X))
	return means,covmat

def qdaLearn(X,y):
    # Inputs
    # X - a N x d matrix with each row corresponding to a training example
    # y - a N x 1 column vector indicating the labels for each training example
    #
    # Outputs
    # means - A d x k matrix containing learnt means for each of the k classes
    # covmats - A list of k d x d learnt covariance matrices for each of the k classes

    # IMPLEMENT THIS METHOD
	"""
	The implementation of this method is almost the same as ldaLearn
	The process of finding mean is exactly like ldaLearn
	covmats is now a list of covariance matrices
	"""
	#print X.shape ==> 150 *2
	#print y.shape ==> 150 *1
	N = X.shape[0] #number of elements
	d = X.shape[1] #number of attributes
	uniqueArray,k = findClassesInY(y); #number of classes

	means = np.zeros([d,k], dtype=float) # 2*5 matrix
	#covmat= np.zeros([np.array([d,d], dtype=float)]) #2*2 matrix

	means,covmats = findMeanByClassWithCovar(X,y,k)

	return means,covmats

def ldaTest(means,covmat,Xtest,ytest):
    # Inputs
    # means, covmat - parameters of the LDA model
    # Xtest - a N x d matrix with each row corresponding to a test example
    # ytest - a N x 1 column vector indicating the labels for each test example
    # Outputs
    # acc - A scalar accuracy value
    # ypred - N x 1 column vector indicating the predicted labels

    # IMPLEMENT THIS METHOD
	#X = 100*2 matrix, Y = 100*1 matrix
	#means = 2*5 , covmat = 2*2 matrix
	acc   =0.0;
	N 	  = Xtest.shape[0] # number of test examples
	d = Xtest.shape[1]
	numClass = means.shape[1] # number of means
	ypred = np.zeros([N,1], dtype = float);
	invCov= inv(covmat) #compute inverse(sigma)

	constantTerm = 1 / (sqrt(np.power(2 * pi,d))  * sqrt(det(covmat))) #the constant term in p(x) formula

	"""The idea is to look at all the test examples given in Xtest, and apply the formula for computing p(x) to the dataset
	The predicted label will be the one where the p(x) is maximum (different values of means will be tried out)"""

	for i in range(N): #for all training rows
		pdf = 0
		testX_transpose = np.transpose(Xtest[i,:]) #required for (X-mu) operation
		prediction = getPredictedLabel(testX_transpose,means,invCov,numClass,constantTerm)
		#print "prediction ",prediction
		if (prediction == ytest[i]): #check if prediction matches
			acc += 1 #correct prediction
		ypred[i] = prediction
	acc = acc / N #prediction accuracy percentage
	return acc,ypred

def qdaTest(means,covmats,Xtest,ytest):
    # Inputs
    # means, covmats - parameters of the QDA model
    # Xtest - a N x d matrix with each row corresponding to a test example
    # ytest - a N x 1 column vector indicating the labels for each test example
    # Outputs
    # acc - A scalar accuracy value
    # ypred - N x 1 column vector indicating the predicted labels

    # IMPLEMENT THIS METHOD

	acc   =0.0;
	N 	  = Xtest.shape[0] # number of test examples
	d = Xtest.shape[1]
	numClass = means.shape[1] # number of means
	ypred = np.zeros([N,1], dtype = float);
	invCov= np.copy(covmats) #creates list of same size, basically that's all I use it for, all values are over-written later
	#print "numClass ",numClass
	#print len(covmats)
	for i in range(numClass): #for each of the k class, compute inverse(sigma)
		invCov[i] = inv(covmats[i])

	constantTerm = np.zeros(numClass) # list of length numClass
	constantValue = sqrt(np.power(2 * pi,d))
	for i in range(numClass):
		constantTerm[i] = 1 / (constantValue  * sqrt(det(covmats[i]))) #the constant term in p(x) formula

	"""
	The idea is to look at all the test examples given in Xtest, and apply the formula for computing p(x) to the dataset
	The predicted label will be the one where the p(x) is maximum (different values of means will be tried out)
	"""

	for i in range(N): #for all training rows
		pdf = 0
		testX_transpose = np.transpose(Xtest[i,:]) #required for (X-mu) operation
		#for k in range(numClass):
		prediction = getPredictedLabelForQDA(testX_transpose,means,invCov,numClass,constantTerm)
		#print "prediction ",prediction
		if (prediction == ytest[i]): #check if prediction matches
			acc += 1 #correct prediction
		ypred[i] = prediction
	acc = acc / N #prediction accuracy percentage
	return acc,ypred

def learnOLERegression(X,y):
    # Inputs:
    # X = N x d
    # y = N x 1
    # Output:
    # w = d x 1
    # IMPLEMENT THIS METHOD
	N = X.shape[0]
	d = X.shape[1]
	"""
	Using the formula w = inverse(X.transpose * X) * (X.transpose * y)
	"""
	Xtranspose_X = np.dot(np.transpose(X),X)
	Xtranspose_Y = np.dot(np.transpose(X),y)
	w = np.dot(inv(Xtranspose_X),Xtranspose_Y)
	# without intercept :(64, 64)
	# with intercept    : (65, 65)
	#print w.shape
	return w

def learnRidgeRegression(X,y,lambd):
    # Inputs:
    # X = N x d
    # y = N x 1
    # lambd = ridge parameter (scalar)
    # Output:
    # w = d x 1

    # IMPLEMENT THIS METHOD
	N = X.shape[0]
	d = X.shape[1]
	"""
	Using the formula w = inverse(X.transpose * X) * (X.transpose * y)
	"""
	Xtranspose_X = np.dot(np.transpose(X),X)
	#print "XTranspose_X shape",Xtranspose_X.shape
	lI=np.zeros((d,d))
	np.fill_diagonal(lI,lambd)
	#print "lambda x I :",lI
	Xtranspose_Sum=Xtranspose_X+lI
	Xtranspose_Y = np.dot(np.transpose(X),y)
	w = np.dot(inv(Xtranspose_Sum),Xtranspose_Y)
	return w

def testOLERegression(w,Xtest,ytest):
    # Inputs:
    # w = d x 1
    # Xtest = N x d
    # ytest = N x 1
    # Output:
    # rmse

	#Xtest : 200 * 64
	#Ytest : 200 * 1
	#w     : 64  * 64
    # IMPLEMENT THIS METHOD
	#print Xtest.shape
	#print "w shape",w.shape
	#print ytest.shape
	N = Xtest.shape[0]
	"""
	We use the shortcut np.dot(transpose(y- Xw),(y-Xw)) to rid ourselves of the summation term from the RMSE equation
	"""
	rmse  = 0.0
	temp1 = np.dot(Xtest,w)
	#print "temp1 ",temp1.shape
	temp_rmse = (ytest - temp1)
	#print "temp_rmse ",temp_rmse.shape
	rmse      = np.sum(np.dot(np.transpose(temp_rmse),temp_rmse))

	#print rmse.shape
	rmse = sqrt(rmse / N)
	#print "rmse ",rmse
	return rmse

def regressionObjVal(w, X, y, lambd):

    # compute squared error (scalar) and gradient of squared error with respect
    # to w (vector) for the given data X and y and the regularization parameter
    # lambda

    # IMPLEMENT THIS METHOD

	N=X.shape[0]
	d=X.shape[1]
	error=0;
	grad=np.zeros(w.shape[0])

	"""
	for i in range(0,N):

		#Xi = np.zeros([X.shape[1],1])
		#print "Shape of Xi",Xi.shape
		Xi=np.transpose(X[i,:])
		#print "Shape of Xi",Xi.shape
		Wtranspose=np.transpose(w)
		#print "Shape of Wtranspose",Wtranspose.shape
		term1 = (y[i,:] - np.dot(Wtranspose,Xi))
		#print "Shape of term1",term1.shape
		error+=term1*term1
		out=np.multiply((-1*term1),Xi)
		#print "Shape of w : ",w.shape
		#print "grad : ",grad.shape
		grad+=out

	error_grad=grad
	"""

	Xi=np.transpose(X)
	#print "Shape of Xi",Xi.shape
	#print "Shape of y",y.shape
	Wtranspose=w.reshape([w.shape[0],1])
	#print "Shape of Wtranspose",Wtranspose.shape
	term1 = (y - np.dot(X,Wtranspose))
	#print "Shape of term1",term1.shape
	error=np.sum(np.square(term1))
	grad=np.dot(-1,np.dot(Xi,term1))
	#print "Shape of w : ",w.shape
	#print "grad : ",grad.shape
	#grad+=out
	error_grad=grad[:,0]+np.dot(lambd,w)

	error=error/2

	"""
	Adding lambda term
	"""

	error=error + (0.5*lambd*np.sum(np.square(w)))
	return error,error_grad

def mapNonLinear(x,p):
    # Inputs:
    # x - a single column vector (N x 1)
    # p - integer (>= 0)
    # Outputs:
    # Xd - (N x (d+1))
    # IMPLEMENT THIS METHOD
    Xd = np.ones((x.shape[0],p+1))
    i = 0
    for xi in x:
		j = 1
		while(j<p+1):
			Xd[i][j] = pow(xi,j)
			j = j + 1
		j = 1
		i = i +1
    return Xd

# Main script

# Problem 1
# load the sample data
if sys.version_info.major == 2:
    X,y,Xtest,ytest = pickle.load(open('sample.pickle','rb'))
else:
    X,y,Xtest,ytest = pickle.load(open('sample.pickle','rb'),encoding = 'latin1')

# LDA
means,covmat = ldaLearn(X,y)
ldaacc = ldaTest(means,covmat,Xtest,ytest)
print('LDA Accuracy = '+str(ldaacc))
# QDA
means,covmats = qdaLearn(X,y)
qdaacc = qdaTest(means,covmats,Xtest,ytest)
print('QDA Accuracy = '+str(qdaacc))

# plotting boundaries
x1 = np.linspace(-5,20,100)
x2 = np.linspace(-5,20,100)
xx1,xx2 = np.meshgrid(x1,x2)
xx = np.zeros((x1.shape[0]*x2.shape[0],2))
xx[:,0] = xx1.ravel()
xx[:,1] = xx2.ravel()

zacc,zldares = ldaTest(means,covmat,xx,np.zeros((xx.shape[0],1)))
plt.contourf(x1,x2,zldares.reshape((x1.shape[0],x2.shape[0])))
plt.scatter(Xtest[:,0],Xtest[:,1],c=ytest)

plt.show()

zacc,zqdares = qdaTest(means,covmats,xx,np.zeros((xx.shape[0],1)))
plt.contourf(x1,x2,zqdares.reshape((x1.shape[0],x2.shape[0])))
plt.scatter(Xtest[:,0],Xtest[:,1],c=ytest)

plt.show()

# Problem 2

if sys.version_info.major == 2:
    X,y,Xtest,ytest = pickle.load(open('diabetes.pickle','rb'))
else:
    X,y,Xtest,ytest = pickle.load(open('diabetes.pickle','rb'),encoding = 'latin1')

# add intercept
X_i = np.concatenate((np.ones((X.shape[0],1)), X), axis=1)
Xtest_i = np.concatenate((np.ones((Xtest.shape[0],1)), Xtest), axis=1)

w = learnOLERegression(X,y)
mle = testOLERegression(w,Xtest,ytest)

w_i = learnOLERegression(X_i,y)
mle_i = testOLERegression(w_i,Xtest_i,ytest)

print('RMSE without intercept '+str(mle))
print('RMSE with intercept '+str(mle_i))

# Problem 3
k = 101
lambdas = np.linspace(0, 1, num=k)
i = 0
rmses3 = np.zeros((k,1))
for lambd in lambdas:
    w_l = learnRidgeRegression(X_i,y,lambd)
    rmses3[i] = testOLERegression(w_l,Xtest_i,ytest)
    i = i + 1
plt.plot(lambdas,rmses3)

plt.show()

# Problem 4
k = 101
lambdas = np.linspace(0, 1, num=k)
i = 0
rmses4 = np.zeros((k,1))
opts = {'maxiter' : 100}    # Preferred value.
w_init = np.ones((X_i.shape[1],1))
for lambd in lambdas:
    args = (X_i, y, lambd)
    w_l = minimize(regressionObjVal, w_init, jac=True, args=args,method='CG', options=opts)
    w_l = np.transpose(np.array(w_l.x))
    w_l = np.reshape(w_l,[len(w_l),1])
    rmses4[i] = testOLERegression(w_l,Xtest_i,ytest)
    i = i + 1
plt.plot(lambdas,rmses4)
plt.show()

# Problem 5
pmax = 7
lambda_opt = lambdas[np.argmin(rmses4)]
rmses5 = np.zeros((pmax,2))
for p in range(pmax):
    Xd = mapNonLinear(X[:,2],p)
    Xdtest = mapNonLinear(Xtest[:,2],p)
    w_d1 = learnRidgeRegression(Xd,y,0)
    rmses5[p,0] = testOLERegression(w_d1,Xdtest,ytest)
    w_d2 = learnRidgeRegression(Xd,y,lambda_opt)
    rmses5[p,1] = testOLERegression(w_d2,Xdtest,ytest)
plt.plot(range(pmax),rmses5)
plt.legend(('No Regularization','Regularization'))
plt.show()

import numpy,from numpy,import scipy,from scipy


import numpy as np

def cost_default(AL, Y):
    # return cost of a network
    #
    # input:
    #   - AL:   activation vector of last layer
    #   - Y:    expected output
    #
    # output:
    #   - cost: cost of network

    m = Y.shape[1]
    cost = -(1.0/m) * np.sum(Y * np.log(AL) + (1-Y) * np.log(1-AL))

    return cost

def cost_default_prime(AL, Y):
    # returns the derivative of default cost function
    #
    # input:
    #   - AL:   activation vector of last layer
    #   - Y:    expected output
    #
    # output:
    #   - dAL:  partial derivative of cost w.r.t. AL

    dAL = -(np.divide(Y, AL) - np.divide(1-Y, 1-AL))

    return dAL


import numpy as np
from scipy.optimize import minimize

class LinearRegression:
    def __init__(self, l1: float = 0, l2: float = 0) -> None:
        self.l1: float = l1
        self.l2: float = l2
        self.w: np.ndarray = None

    def train(self, X: np.ndarray, Y: np.ndarray) -> None:
        X = np.asarray(X)
        self.w = minimize(
            lambda w: self.__error(w, np.concatenate((np.ones((X.shape[0], 1)), X), axis=1), Y),
            x0=np.zeros(X.shape[1] + 1)
        ).x

    def predict(self, X: np.ndarray) -> np.ndarray:
        X = np.asarray(X)
        return np.concatenate((np.ones((X.shape[0], 1)), X), axis=1) @ self.w

    def MSE(self, X: np.ndarray, Y: np.ndarray) -> float:
        X = np.asarray(X)
        return np.square(
            self.predict(X) - Y
        ).mean()

    def __error(self, w: np.ndarray, X: np.ndarray, Y: np.ndarray) -> float:
        return np.mean(np.square(X @ w - Y)) \
               + self.l1 * np.sum(np.abs(w)) \
               + self.l2 * np.sum(np.square(w))

    def score(self, X: np.ndarray, Y: np.ndarray) -> float:
        ss_res = np.sum((self.predict(X) - Y) ** 2)
        ss_tot = np.sum((Y - np.mean(Y)) ** 2)

        return 1 - ss_res / ss_tot


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

x_data = [ 338.,  333.,  328. , 207. , 226.  , 25. , 179. ,  60. , 208.,  606.]
y_data = [  640.  , 633. ,  619.  , 393.  , 428. ,   27.  , 193.  ,  66. ,  226. , 1591.]

x = np.arange(-200, -100, 1) # bias
y = np.arange(-5, 5, 0.1) # weight
Z = np.zeros((len(x), len(y)))
X, Y = np.meshgrid(x, y) # 把向量擴展成矩陣

for i in range(len(x)):
    for j in range(len(y)):
        b = x[i]
        w = y[j]
        Z[j][i] = 0
        for n in range(len(x_data)):
            Z[j][i] = Z[j][i] + (y_data[n] - b - w * x_data[n]) ** 2
        Z[j][i] = Z[j][i] / len(x_data)

# ydata = b + w * xdata
b = -120 # initial b
w = -4 # initial w
lr = 1 # learning rate
iteration = 100000

b_grad_last = 0
w_grad_last = 0

# Store initial values for plotting
b_history = [b]
w_history = [w]

x_data, y_data = np.array(x_data), np.array(y_data)

# Iterations
for i in range(iteration):
    b_grad = -2.0 * (y_data - b - w * x_data)
    b_grad = np.sum(b_grad) / len(b_grad)
    w_grad =  np.dot(x_data.transpose(), -2.0 * (y_data - b - w * x_data))
    #print('{}. b_grad:'.format(i), b_grad, ', {}. w_grad:'.format(i), w_grad)

    b_grad_last = b_grad_last + b_grad ** 2
    w_grad_last = w_grad_last + w_grad ** 2
    #print('{}. b_grad_last:'.format(i), b_grad_last, ', {}. w_grad_last:'.format(i), w_grad_last)

    # Update parameters(Use Adagrad)
    b = b - lr/np.sqrt(b_grad_last) * b_grad
    w = w - lr/np.sqrt(w_grad_last) * w_grad

    # Store parameters for plotting
    b_history.append(b)
    w_history.append(w)

# plot the figure
plt.contourf(x,y,Z, 50, alpha=0.5, cmap=plt.get_cmap('jet'))
plt.plot([-188.4], [2.67], 'x', ms=12, markeredgewidth=3, color='orange')
plt.plot(b_history, w_history, 'o-', ms=3, lw=1.5, color='black')
plt.xlim(-200,-100)
plt.ylim(-5,5)
plt.xlabel(r'$b$', fontsize=16)
plt.ylabel(r'$w$', fontsize=16)
plt.show()


import numpy as np
import math
from scipy.optimize import curve_fit

def calculate_summary_of_sample(sample):
    sample = np.array(sample, dtype=float)
    return np.sum(sample)

# definition of  sigmoid curve
def sigmoid_curve(x, a, b):
    return 1. / (1.0 + np.exp(-a * (x - b)))

# fit sigmoid curve with least squares method
def fit_sigmoid_curve(x_series, y_series):
    log_of_x = []
    for x in x_series:
        log_of_x.append(math.log(x, 10))

    y_series = np.array(y_series, dtype=float)
    popt, pcov = curve_fit(sigmoid_curve, log_of_x, y_series, maxfev=5000)

    x_sampling = np.linspace(np.min(log_of_x), np.max(log_of_x), 1000)
    y_sampling = sigmoid_curve(x_sampling, *popt)

    error_of_y_sampling = []
    for y in y_sampling:
        error_of_y_sampling.append(abs(y - 0.5))
    min_error = np.min(error_of_y_sampling)
    min_index = error_of_y_sampling.index(min_error)
    ec50 = sigmoid_curve(x_sampling[min_index], *popt)

    return x_sampling[min_index], ec50, x_sampling, y_sampling


import numpy as np
from scipy import stats
import pandas as pd

xbar = 990
h0 = 1000
s = 12.5
n = 30

st = (xbar - h0) / (s / np.sqrt(float(n)))
#print(st)

# t-table
alpha = 0.05
t_alpha = stats.t.ppf(alpha, n-1) # 신뢰수준, df
#print(t_alpha) # 임계치보다 검정 통계량이 작다 -> 기각

# P-VALUE
p_val = stats.t.sf(np.abs(st), n-1)
#print(p_val) # 0.05 > 0.0007 --> 기각

## X2 ##
survey = pd.read_csv("Chapter01/survey.csv")
survey_tab = pd.crosstab(survey.Smoke, survey.Exer, margins=True)
observed = survey_tab.ix[:-1, :-1]
contg = stats.chi2_contingency(observed=observed)
p_value = round(contg[1], 3)
# p_value = 0.483, 차이가 없다

fet = pd.read_csv("Chapter01/fetilizers.csv")
anova = stats.f_oneway(fet.fertilizer1, fet.fertilizer2, fet.fertilizer3)
# F_onewayResult(statistic=3.6634935025687523, pvalue=0.05063590143901569)
# 기각 X // 세 집단 중 어느 집단도 차이가 보이지 않는다.


import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import tensorflow as tf
print(tf.__version__)

from sklearn.datasets import make_regression

# the equation 2 * x^3 - 40 * x^2 + 9 * x + 24
n = 10000
X = np.random.randn(n)
randomize = np.random.randint(-100,100, size = n)
y = []
for i in range(n):
    y.append((2*X[i]**3)-(40*X[i]**2)+(9*X[i])+24)

for i in range(n):
    y[i] = y[i] + randomize[i]

datadict = {'data': X, 'target': y}
data = pd.DataFrame(data=datadict)
plt.scatter(X,y)
plt.show()

X = data.iloc[:,[0]].values
type(X)

y = data.target.values

# TRAIN TEST SPLIT
from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2)

N, D = X_train.shape

from sklearn.preprocessing import StandardScaler
scaleObj = StandardScaler()
X_train = scaleObj.fit_transform(X_train)
X_test = scaleObj.transform(X_test)

from tensorflow.keras.layers import Input, Dense, Activation,Dropout
from tensorflow.keras.models import Model

input_layer = Input(shape=(D,))
dense_layer_1 = Dense(20, activation='relu')(input_layer)
dense_layer_2 = Dense(20, activation='relu')(input_layer)
output = Dense(1)(dense_layer_2)

model = Model(inputs=input_layer, outputs=output)

model.compile(
    optimizer = 'adam',
    loss = 'mse',
    metrics = ['mse']
)

# https://www.tensorflow.org/api_docs/python/tf/keras/callbacks/LearningRateScheduler
def scheduler(epoch):
  if epoch < 10:
    return 0.001
  else:
    return 0.001 * tf.math.exp(0.1 * (10 - epoch))

callback = tf.keras.callbacks.LearningRateScheduler(scheduler)

report = model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=200)

plt.plot(report.history['loss'], label="loss = SGD")

print(X.shape)
print(y.shape)

y_predicted = model.predict(X)
plt.scatter(X,y, color='b')
plt.scatter(X,y_predicted, color='r')
plt.show()

print("Train eval: ", model.evaluate(X_train, y_train))
print("Test eval: ", model.evaluate(X_test, y_test))


import math
import numpy as np
import numpy.random as rn

class SA:
  def __init__(self, initial, fn_fitness, fn_cooler, fn_next_state, fn_acceptance, maxsteps=1000):
    self.initial = initial
    self.fn_fitness = fn_fitness
    self.fn_cooler = fn_cooler
    self.fn_next_state = fn_next_state
    self.fn_acceptance = fn_acceptance
    self.maxsteps = maxsteps

  def anneal(self):
    state = self.initial
    cost = self.fn_fitness(state)
    for step in range(self.maxsteps):
      fraction = step / float(self.maxsteps)
      temperature = self.fn_cooler(fraction)
      new_state = self.fn_next_state(state, fraction)
      new_cost = self.fn_fitness(new_state)
      if self.fn_acceptance(cost, new_cost, temperature) > rn.random():
        state, cost = new_state, new_cost
    return state

class SAAckley:
  def __init__(self, interval):
    self.interval = interval
    self.start = (self.randomize(), self.randomize())

  def randomize(self):
    a, b = self.interval
    return a + (b - a) * rn.random_sample()

  def fitness(self, state):
    x, y = state
    # Ackley's Function
    return -20.0*math.exp(-0.2*math.sqrt(0.5*((x**2)+(y**2)))) - math.exp(0.5*(math.cos(2.0*math.pi*x)+math.cos(2.0*math.pi*y))) + math.e + 20

  def cooler(self, fraction):
    return max(0.01, min(1, 1 - fraction))

  def next_state(self, state, fraction):
    spread = (max(self.interval) - min(self.interval)) * fraction / 10
    delta1 = (-spread/2.) + spread * rn.random_sample()
    delta2 = (-spread/2.) + spread * rn.random_sample()
    return (self.clip(state[0] + delta1), self.clip(state[1] + delta2))

  def clip(self, x):
    a, b = self.interval
    return max(min(x, b), a) # Force x into the interval

  def acceptance(self, cost, new_cost, temperature):
    return 1 if new_cost < cost else np.exp(- (new_cost - cost) / temperature)

problem = SAAckley(interval=(-5, 5))
sa = SA(
  initial = problem.start,
  fn_fitness = problem.fitness,
  fn_cooler = problem.cooler,
  fn_next_state = problem.next_state,
  fn_acceptance = problem.acceptance,
  maxsteps=1000
  )
solution = sa.anneal();
print(solution, problem.fitness(solution))


from collections import Counter
import numpy as np

def calculate_pmf(y):
    """
    calculate the probability mass function given sample data.
    """
    assert(len(y.shape) == 1)
    # values = np.unique(y)
    counter = Counter(y)
    for k, v in counter.items():
        counter[k] = v / len(y)
    return counter

def calculate_entropy(pmf):
    """
    calculate entropy of a probability mass function

    Inputs
    ------
    - pmf: list or numpy array, dimension (N, ), probability mass function, or dict
    """
    if isinstance(pmf, dict):
        pmf = list(pmf.values())
    entropy = sum([-p * np.log2(p) for p in pmf])
    print("entropy: ", entropy, pmf)
    return entropy

def calculate_gini_index(pmf: list):
    if isinstance(pmf, dict):
        pmf = list(pmf.values())
    return 1 - sum([p**2 for p in pmf])

def calculate_variance(X):
    mu = np.mean(X)
    return np.sum([(x - mu)**2 for x in X])

def calculate_cross_entropy(Y, T):
    return sum([-T[i] * np.log2(y) for i, y in enumerate(Y)])

def precision_score(Y, T):
    """
    calculate true positive ratio for binary classification: 0 and 1 labeled
    """
    if not isinstance(Y, np.ndarray):
        Y = np.array(Y)
    if not isinstance(T, np.ndarray):
        T = np.array(T)
    tp = (Y[T == 1] == 1) # true positive
    pp = Y == 1 # predicted positive: true positive + false positive
    precision = np.sum(tp) / np.sum(pp)
    return precision

def recall_score(Y, T):
    if not isinstance(Y, np.ndarray):
        Y = np.array(Y)
    if not isinstance(T, np.ndarray):
        T = np.array(T)
    tp = (Y[T == 1] == 1) # true positive
    sp = T == 1# all sample positives: true positive + false negative
    recall = np.sum(tp) / np.sum(sp)
    return recall

def f1_score(Y, T):
    """
    F1 score is the harmonic mean of precision and recall
    """
    precision = precision_score(Y, T)
    recall = recall_score(Y, T)
    f1 = 2*precision*recall/(precision + recall)
    print(precision, recall, f1, format(f1, '.6f'))
    return f1


import numpy as np
import matplotlib.pyplot as plt

def RMSE(T,S):
    # S Simulater or calculated
    # T Measured
    E=0
    # Estimates the sum of the differences
    E=(T-S)**2
    E=np.nansum(E)

    #    E=E+(m-s)**2
    #for m,s in zip(T,S):
    E=E**(1/2)
    # Estimates root square and averages it
    E=E/len(T)

    return E

def MSE(T,S):
    # S Simulater or calculated
    # T Measured
    E=0
    # Estimates the sum of the square differences
    E=(T-S)**2
    E=np.nansum(E)
    E=E/len(T)
    return E

def PlotError(M,S):
    figure, axes=plt.subplots(nrows=2,ncols=1)
    plt.subplot(2,1,1)
    plt.plot(M)
    plt.plot(S)
    plt.ylabel("Value of the time series")
    plt.subplot(2,1,2)
    plt.title("Error (Measured - Simulated)")
    plt.plot(M-S)
    plt.xlabel("Time series (h)")
    plt.ylabel("Error")
    figure.tight_layout(pad=3.0)

def PlotValue(Mytext):
    plt.figure()
    plt.axis('off')
    plt.text(0.6, 0.7, Mytext, size=50, rotation=0.,
         ha="center", va="center",
         bbox=dict(boxstyle="round",
                   ec=(1., 0.5, 0.5),
                   fc=(1., 0.8, 0.8),
                   )
         )

def Error1(T=np.array([]),S=np.array([])):
    Temp=RMSE(T,S)
    R={"RMSE":Temp , "sd_T":np.std(T),"MSE":MSE(T,S), "sd_S":np.std(S),
    "NRMSE":Temp/np.std(T),
    "Nash": 1-np.nansum((T-S)**2)/np.nansum((T-np.nanmean(T))**2),
    "Cor":np.nansum((S-np.nanmean(S))*(T-np.nanmean(T)))/(np.sqrt(np.nansum((S-np.nanmean(S))**2))*np.sqrt(np.nansum((T-np.nanmean(T))**2)))
    }
    PlotError(T,S)
    PlotValue("RMSE="+str(R["RMSE"]))
    return R


import config
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

# Hypothesis Function (Sigmoid)
def hypothesis(thetarg, x):
    return 1 / (1 + np.exp(-np.dot(x, thetarg)))

# Cost function used to calculate the error between hypothetic and actual value over m training examples
def cost(x, y, thetarg, msize):
    return float((1 / msize) * (
                -np.dot(y.T, np.log(hypothesis(thetarg, x))) - np.dot((1 - y).T, np.log(1 - hypothesis(thetarg, x)))))

# Gradient Descent method to minimize cost function in configurable alpha and iterations
def gradient_descent(x, y, thetarg, msize):
    jvec = []
    theta_history = []
    for i in range(config.num_iterations):
        theta_history.append(list(thetarg[:, 0]))
        jvec.append(cost(x, y, thetarg, msize))

        for j in range(len(thetarg)):
            thetarg[j] = thetarg[j] - (config.alpha / msize) * np.sum(
                (hypothesis(thetarg, x) - y) * np.array(x[:, j]).reshape(msize, 1))
    return thetarg

# Prediction to classify cancer as benign or malignant
def predict(theta_final, input_matrix):
    h = hypothesis(theta_final, input_matrix)
    pred = []
    for i in h:
        if i > 0.5:
            pred.append(1)
        else:
            pred.append(0)
    return pred

# Accuracy check on the training dataset
def accuracy(prediction, decision):
    count = 0
    for i, j in zip(prediction, decision):
        if i == j:
            count = count + 1
    return 100 * (count / len(prediction))

# Loading test1 and test2 as features for training data with decision label
muldata = pd.read_csv(config.path)
data = np.loadtxt(config.path, delimiter=',', usecols=[0, 1, 2], unpack=True)
X = np.transpose(np.array(data[:-1]))
inmatrix = np.insert(X, 0, 1, axis=1)
outmatrix = np.transpose(np.array(data[-1:]))
m = outmatrix.size
theta = np.zeros([inmatrix.shape[1], 1])

# Scatter Plot to visualize positive and negative examples
plt.title("Training Classification")
plt.xlabel("score1")
plt.ylabel("score2")
color = ['red' if l == 0 else 'green' for l in outmatrix]
plt.scatter(inmatrix[:, 1], inmatrix[:, 2], color=color)

# Getting best parameters by running gradient descent
final_theta = gradient_descent(inmatrix, outmatrix, theta, m)

# Prediction and accuracy of the classifier
predict_label = predict(final_theta, inmatrix)
accuracy = accuracy(predict_label, outmatrix)

# Scatter Plot to visualize predicted data
plt.title("Hypothesis Classification")
plt.xlabel("Score1")
plt.ylabel("Score2")
color = ['red' if l == 0 else 'green' for l in predict_label]
plt.scatter(inmatrix[:, 1], inmatrix[:, 2], color=color)


# 3.13
# Explore the baseball data
#Because the mean and median are so far apart, you decide to complain to the MLB. They find the error and send the corrected data over to you. It's again available as a 2D Numpy array np_baseball, with three columns.

#The Python script on the right already includes code to print out informative messages with the different summary statistics. Can you finish the job?

#INSTRUCTIONS
#100 XP
#The code to print out the mean height is already included. Complete the code for the median height. Replace None with the correct code.
#Use np.std() on the first column of np_baseball to calculate stddev. Replace None with the correct code.
#Do big players tend to be heavier? Use np.corrcoef() to store the correlation between the first and second column of np_baseball in corr. Replace None with the correct code.

# np_baseball is available

# Import numpy
import numpy as np

# Print mean height (first column)
avg = np.mean(np_baseball[:,0])
print("Average: " + str(avg))

# Print median height. Replace 'None'
med = np.median(np_baseball[:,0])
print("Median: " + str(med))

# Print out the standard deviation on height. Replace 'None'
stddev = np.std(np_baseball[:,0])
print("Standard Deviation: " + str(stddev))

# Print out correlation between first and second column. Replace 'None'
corr = np.corrcoef(np_baseball[:,0], np_baseball[:,1])
print("Correlation: " + str(corr))

Python/Datacamp/0.0_Intro to Python for Data Science/3.13_Explore-the-baseball-data.py


# coding=utf-8

from numpy import random, mat, eye

# 生成一个 4*4 的随机数组
randArray = random.rand(4, 4)

# 转化关系， 数组转化为矩阵
randMat = mat(randArray)
'''
.I 表示对矩阵求逆(可以利用矩阵的初等变换)
   意义：逆矩阵是一个判断相似性的工具。逆矩阵A与列向量p相乘后，将得到列向量q，q的第i个分量表示p与A的第i个列向量的相似度。
   参考案例链接：
   https://www.zhihu.com/question/33258489
   http://blog.csdn.net/vernice/article/details/48506027
.T 表示对矩阵转置(行列颠倒)
    * 等同于: .transpose()
.A 返回矩阵基于的数组
    参考案例链接：
    http://blog.csdn.net/qq403977698/article/details/47254539
'''
invRandMat = randMat.I
TraRandMat = randMat.T
ArrRandMat = randMat.A
# 输出结果
print('randArray=(%s) \n' % type(randArray), randArray)
print('randMat=(%s) \n' % type(randMat), randMat)
print('invRandMat=(%s) \n' % type(invRandMat), invRandMat)
print('TraRandMat=(%s) \n' % type(TraRandMat), TraRandMat)
print('ArrRandMat=(%s) \n' % type(ArrRandMat), ArrRandMat)
# 矩阵和逆矩阵 进行求积 (单位矩阵，对角线都为1嘛，理论上4*4的矩阵其他的都为0)
myEye = randMat*invRandMat
# 误差
print(myEye - eye(4))


import numpy as np
import pandas as pd
from sklearn import BaseEstimator, ClassifierMixin, LogisticRegression

class BayesianClassifier(BaseEstimator, ClassifierMixin):
    """
    Note: still differs from Pablo's R version, so it needs fixing, but hopefully it's a headstart.

    Similar to a Naive Bayes classifier
    Using the assumption of independence of features, it fits a model for each feature a combines them.
    This is done separately for each class, i.e. it fits multiple one-vs-all models in the multiclass case.
    The independence assumption allows for more transparent interpretation at some cost of performance.

    Note that test data should be scaled the same way as training data for meaningful results.
    """

    def __init__(self):
        self.regressions_ = None
        self.classes_ = None
        self.priors_ = None
        self.prior_log_odds_ = None

    def fit(self, x, y):
        """
        :param x: Pandas DataFrame, (n_samples, n_features)
        :param y: Pandas Series, (n_samples,)
        :return: self
        """
        self.classes_ = np.array(sorted(set(y.values)))
        self.priors_ = y.value_counts().loc[self.classes_] / len(y)
        self.prior_log_odds_ = np.log(self.priors_ / (1 - self.priors_))
        self.regressions_ = dict()
        for k in self.classes_:
            self.regressions_[k] = dict()
            y_one_v_all = y.copy()
            y_one_v_all[y != k] = 0
            y_one_v_all[y == k] = 1
            for feature in x.columns:
                logreg = LogisticRegression()
                subdf = x.loc[:, [feature]]
                logreg.fit(subdf, y_one_v_all)
                self.regressions_[k][feature] = logreg
        return self

    def predict_proba(self, x, normalize=True, return_all=False):
        prior_evidence = pd.Series(index=self.classes_)
        log_odds = pd.DataFrame(index=x.index, columns=self.classes_)
        feature_evidence = {
            k: pd.DataFrame(index=x.index, columns=x.columns)
            for k in self.classes_
        }
        for k in self.classes_:
            prior = self.priors_.loc[k]
            prior_odds = prior / (1 - prior)
            prior_log_odds = np.log(prior_odds)
            log_odds.loc[:, k] = prior_log_odds
            prior_evidence.loc[k] = prior_log_odds
            for feature in x.columns:
                logreg = self.regressions_[k][feature]
                subdf = x.loc[:, [feature]]
                class_index = list(logreg.classes_).index(1)
                probs = logreg.predict_proba(subdf)[:, class_index]
                odds = probs / (1 - probs)
                evidence = np.log(odds / prior_odds)
                feature_evidence[k].loc[:, feature] = evidence
                log_odds.loc[:, k] += evidence
        posterior_probs = np.exp(log_odds) / (np.exp(log_odds) + 1)
        if return_all:
            return posterior_probs, feature_evidence
        if normalize:
            posterior_probs = posterior_probs.divide(
                posterior_probs.sum(axis=1), axis='index')
        return posterior_probs

    def predict(self, x):
        posterior_probs = self.predict_proba(x)
        max_idxs = np.argmax(posterior_probs.values, axis=1)
        return pd.Series(self.classes_[max_idxs], index=x.index)


#! /usr/bin/env python

import numpy as np
import matplotlib.pyplot as plt

#Exercise A.2

"""This program includes five functions, each defined as a different sequence
to estimate pi, up to n steps."""

def getN(n):
	"""Just makes an array from 1 to n. Mainly here to be called in seq1."""
	array = np.arange(1,n+1)
	return array

def f1(n):
	"""returns the a_n element of the sequence."""
	An = 0
	#sum over k from 1 to n
	for k in range(1, int(n)+1):
		k = float(k)
		An += ((-1.0)**(k+1.0))/(2*k-1.0)
	An *= 4.0
	return An

def seq1(n, f):
	"""Calls the function of the sequence, returning an array of the elements
	of the sequence from a_1 to a_n, taking args n, f, where n is an int and
	f is a vectorizable function; provided functions are f1, f2, f3, f4, f5.
	"""

	#vectorize the formula for the sequence
	vf = np.vectorize(f)

	#create an array of integers from 1 to n, defines final array as the
	#function acting on that
	array = vf(getN(n))
	return array

def f2(n):
	"""Returns the b_n element of the sequence."""
	Bn = 0
	#sum over k from 1 to n
	for k in range(1, int(n)+1):
		k = float(k)
		Bn += 1/k**2.0
	Bn *= 6.0
	Bn **= 0.5
	return Bn

def f3(n):
	"""Returns the c_n element of the sequence."""
	Cn = 0
	for k in range(1, int(n)+1):
		k = float(k)
		Cn += k**(-4.0)
	Cn *= 90.0
	Cn **= .25
	return Cn

def f4(n):
	"""Returns the d_n element of the sequence."""
	Dn = 0
	for k in range(0, int(n)+1):
		k = float(k)
		Dn += ((-1.0)**k)/((3.0**k)*(2.0*k+1.0))
	Dn *= (6.0/np.sqrt(3.0))
	return Dn

def f5(n):
	En = 0
	for k in range(0, int(n)+1):
		k = float(k)
		En += (4.0*((-1.0)**k))/((5.0**(2.0*k+1.0))*(2.0*k+1.0))
		En -= ((-1.0)**k)/((239.0**(2.0*k+1.0))*(2.0*k+1.0))
	En *= 4.0
	return En

def plotSeq(n,f):
	"""Plots the sequence, a_n vs n, taking a defined function f1, f2,
	f3, f4 or f5 as a function to plot. (Does this by calling seq1, and
	plotting the result of that against getN()."""
	plt.plot(getN(n), seq1(n,f), 'bo')
	plt.xlabel('n')
	plt.ylabel('a_n')
	plt.show()

def plotAll(n):
	"""Plots all the sequences, to show how quickly they converge to pi."""
	plt.hold('on')
	plt.plot(getN(n),seq1(n,f1),getN(n),seq1(n,f2),getN(n),seq1(n,f3),getN(n),seq1(n,f4),getN(n),seq1(n,f5),)
	plt.legend(['Seq1','Seq2','Seq3','Seq4','Seq5'])
	plt.show()

#Following tests test the designated functions,
#for n = 1
def test_f1():
	shouldBe = 4.0
	assert shouldBe == f1(1)

def test_f2():
	shouldBe = 6.0**.5
	assert shouldBe == f2(1)

def test_f3():
	shouldBe = 90.0**.25
	assert shouldBe == f3(1)

def test_4():
	shouldBe = -((6.0)/(np.sqrt(3.0)))*(1.0/9.0)
	assert shouldBe == f4(1)

def test_5():
	shouldBe = -(16.0)/(375.0) + 4.0/((239.0**3.0)*3.0)
	assert shouldBe == f5(1)

def test_seq1():
	testResult = np.array([4.0])
	assert testResult == seq1(1, f1)


#Description: Contains logic for calculating the fractal dimension of an image.
#Contributor(s): Eric Stenton

import sys
import numpy as np
import pylab as pl
import imageio

def rgb2gray(rgb):
    r, g, b = rgb[:,:,0], rgb[:,:,1], rgb[:,:,2]
    gray = 0.2989 * r + 0.5870 * g + 0.1140 * b
    return gray

# Minkowski–Bouligand Dimension
def fractal_dimension_minkowski_bouligand(Z, threshold=0.9):
    # Prepare image
    imageArray = imageio.imread(Z)

    if (len(imageArray.shape) == 3):
        Z = rgb2gray(imageArray)

        # Only for 2d image
        assert(len(Z.shape) == 2)

        # From https://github.com/rougier/numpy-100 (#87)
        def boxcount(Z, k):
            S = np.add.reduceat(
                np.add.reduceat(Z, np.arange(0, Z.shape[0], k), axis=0),
                                   np.arange(0, Z.shape[1], k), axis=1)

            # We count non-empty (0) and non-full boxes (k*k)
            return len(np.where((S > 0) & (S < k*k))[0])

        # Transform Z into a binary array
        Z = (Z < threshold)

        # Minimal dimension of image
        p = min(Z.shape)

        # Greatest power of 2 less than or equal to p
        n = 2**np.floor(np.log(p)/np.log(2))

        # Extract the exponent
        n = int(np.log(n)/np.log(2))

        # Build successive box sizes (from 2**n down to 2**1)
        sizes = 2**np.arange(n, 1, -1)

        # Actual box counting with decreasing size
        counts = []
        for size in sizes:
            counts.append(boxcount(Z, size))

        # Fit the successive log(sizes) with log (counts)
        coeffs = np.polyfit(np.log(sizes), np.log(counts), 1)
        return -coeffs[0]

def fractal_dimension_hausdorff(image):
    # Prepare image
    imageArray = imageio.imread(image)

    if (len(imageArray.shape) == 3):
        # Prepare image
        image = rgb2gray(imageArray)

        # finding all the non-zero pixels
        pixels=[]
        for i in range(image.shape[0]):
            for j in range(image.shape[1]):
                if image[i,j]>0:
                    pixels.append((i,j))

        Lx=image.shape[1]
        Ly=image.shape[0]
        pixels=pl.array(pixels)

        # computing the fractal dimension
        # considering only scales in a logarithmic list
        scales=np.logspace(0.01, 1, num=10, endpoint=False, base=2)
        Ns=[]
        # looping over several scales
        for scale in scales:
            # computing the histogram
            H, edges=np.histogramdd(pixels, bins=(np.arange(0,Lx,scale),np.arange(0,Ly,scale)))
            Ns.append(np.sum(H>0))

        # linear fit, polynomial of degree 1
        coeffs=np.polyfit(np.log(scales), np.log(Ns), 1)

        return -coeffs[0] #the fractal dimension is the OPPOSITE of the fitting coefficient


#http://pymc-devs.github.io/pymc3/getting_started/#case-study-2-coal-mining-disasters

import numpy as np
import matplotlib.pyplot as plt
import pymc3
import pymc3.distributions.timeseries as ts
import pandas as pd
import scipy

disaster_data = np.ma.masked_values([4, 5, 4, 0, 1, 4, 3, 4, 0, 6, 3, 3, 4, 0, 2, 6,
                            3, 3, 5, 4, 5, 3, 1, 4, 4, 1, 5, 5, 3, 4, 2, 5,
                            2, 2, 3, 4, 2, 1, 3, -999, 2, 1, 1, 1, 1, 3, 0, 0,
                            1, 0, 1, 1, 0, 0, 3, 1, 0, 3, 2, 2, 0, 1, 1, 1,
                            0, 1, 0, 1, 0, 0, 0, 2, 1, 0, 0, 0, 1, 1, 0, 2,
                            3, 3, 1, -999, 2, 1, 1, 1, 1, 2, 4, 2, 0, 0, 1, 4,
                            0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1], value=-999)
year = np.arange(1851, 1962)

plt.plot(year, disaster_data, 'o', markersize=8);
plt.ylabel("Disaster count")
plt.xlabel("Year")

plt.show()

from pymc3 import DiscreteUniform, Poisson, switch, Model, Exponential, NUTS, Metropolis, sample, traceplot

with Model() as disaster_model:

    switchpoint = DiscreteUniform('switchpoint', lower=year.min(), upper=year.max(), testval=1900)

    # Priors for pre- and post-switch rates number of disasters
    early_rate = Exponential('early_rate', 1)
    late_rate = Exponential('late_rate', 1)

    # Allocate appropriate Poisson rates to years before and after current
    rate = switch(switchpoint >= year, early_rate, late_rate)

    disasters = Poisson('disasters', rate, observed=disaster_data)

    step1 = NUTS([early_rate, late_rate])

    # Use Metropolis for switchpoint, and missing values since it accommodates discrete variables
    step2 = Metropolis([switchpoint, disasters.missing_values[0]] )

    trace = sample(10000, step=[step1, step2])

traceplot(trace);

import numpy,import scipy,import pymc3,from pymc3


import numpy as np
import pytest

from structure_factor.transforms import HankelTransformBaddourChouinard

def modified_gaussian(x, a, n):
    return np.exp(-np.square(a * x)) * np.power(x, n)

def ht_modified_gaussian(n, x, a):
    ht = np.exp(-np.square(x / (2 * a))) * np.power(x, n)
    ht *= (0.5 / a ** 2) ** (n + 1)
    return ht

def sinc(x, a=1.0):
    return np.sinc(x * (a / np.pi))

def ht_sinc(n, x, a):
    ht = np.full(x.shape, 1.0 / a ** 2)

    mask = x < a
    ht[mask] *= np.cos(np.pi * n / 2) * np.power(x[mask] / a, n)
    ht[mask] /= np.sqrt(1.0 - np.square(x[mask] / a))
    ht[mask] /= np.power(1.0 + np.sqrt(1.0 - np.square(x[mask] / a)), n)

    np.invert(mask, out=mask)  # x > a
    ht[mask] *= np.sin(n * np.arcsin(a / x[mask]))
    ht[mask] /= np.sqrt(np.square(x[mask] / a) - 1.0)
    return ht

def sinc_modified(x, a=1.0):
    return np.sinc(x * (a / np.pi)) / np.square(x)

def ht_sinc_modified(n, x, a):
    ht = np.full(x.shape, 1.0 / n)

    mask = x < a
    ht[mask] *= np.sin(np.pi * n / 2) * np.power(x[mask] / a, n)
    ht[mask] /= np.power(1.0 + np.sqrt(1.0 - np.square(x[mask] / a)), n)

    np.invert(mask, out=mask)  # x > a
    ht[mask] *= np.sin(n * np.arcsin(a / x[mask]))
    return ht

@pytest.fixture
def ht():
    order = 0
    return HankelTransformBaddourChouinard(order)

def test_hankel_transform_f1(ht):
    a = 5
    f = lambda r: modified_gaussian(r, a, ht.order)
    ht_f = lambda k: ht_modified_gaussian(ht.order, k, a)

    r_max = 2
    nb_points = 64
    ht.compute_transformation_parameters(r_max, nb_points)
    k, actual = ht.transform(f)
    desired = ht_f(k)
    np.testing.assert_almost_equal(actual, desired)

def test_hankel_transform_f2(ht):
    a = 5
    f = lambda r: sinc(r, a)
    ht_f = lambda k: ht_sinc(ht.order, k, a)

    r_max = 30
    nb_points = 256
    ht.compute_transformation_parameters(r_max, nb_points)
    k, actual = ht.transform(f)
    desired = ht_f(k)
    np.testing.assert_almost_equal(
        actual,
        desired,
        decimal=0,
        err_msg="No worries if test fails, approximation wiggles around true transform (Gibbs phenomenon)",
    )


""" Implements the cost functions used by the models.

@author: Gabriel G. Nogueira (Talendar)
"""

from abc import ABC, abstractmethod
import numpy as np

class CostFunction(ABC):
    """ Abstract class defining a cost function and its operations. """

    @abstractmethod
    def __call__(self, predictions, labels):
        """ Computes the mean cost. """
        raise NotImplementedError("This method wasn't implemented!")

    @abstractmethod
    def unit(self, prediction, label, derivative=False):
        """ Computes the total cost. """
        raise NotImplementedError("This method wasn't implemented!")

class MeanSquaredError(CostFunction):
    """ Mean Squared Error (MSE) cost function. """

    def __call__(self, predictions, labels):
        """ Computes the mean cost. """
        m = len(labels)
        return np.sum( (labels - predictions.T) ** 2 ) / (2 * m)

    def unit(self, prediction, label, derivative=False):
        """ Computes the total cost. """
        if not derivative:
            return ((label.T - prediction) ** 2) / 2

        return prediction - label.T


import numpy as np

def step_function(x):
    return np.array(x > 0, dtype=np.int)

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

def relu(x):
    return np.maximum(0, x)

def cross_entropy_error(y, t):
    delta = 1e-7
    return -np.sum(t * np.log(y + delta))

def softmax(a):
    c = np.max(a)
    exp_a = np.exp(a - c)
    sum_exp_a = np.sum(exp_a)
    y = exp_a / sum_exp_a
    return y

def numerical_gradient(f, x):
    delta = 1e-4
    return (f(x + delta) - f(x - delta)) / (delta * 2)


import pytest
import numpy as np
from VayDiff import BasicMath as bm
from VayDiff.VayDiff import Diff
from VayDiff.VayDiff import Variable

epsilon = 1e-7

def test_init():
    # test Variable __init__
    # test BasicMath __init__
    return

# Simple operations
def add_function(x):
    return 2+x+x-3

def sub_function(x):
    return 3-x

def mul_function(x):
    return 7 + 3.3*x + x*2.7 + 4

def div_scalar(x):
    return x/3

def div_function(x):
    return x/3 + 6.0/x - 1

def simple_op_complete(x):
    return x*x + x/x + 3*x*2 - 3*(x+2)

def unary(x):
    return 3*(+x) + (-x)

# Testing addition, subtraction, multiplication and division
def test_simple_operators():
    a = Variable(val=3, name='a')
    b = Variable(val=3, name='b')
    c = Variable(val=5, name='c')
    # Addition and subtraction
    t11 = Diff().auto_diff(function = add_function, eval_point = [a])
    t12 = Diff().auto_diff(function = sub_function, eval_point = [a])
    assert(t11.val == 5 and t11.der['a'] == 2)
    assert(t12.val == 0 and t12.der['a'] == -1)

    # Multiplication
    t2 = Diff().auto_diff(function = mul_function, eval_point = [a])
    assert(t2.val == 29)
    assert(t2.der['a'] == 6)

    # Division
    t3 = Diff().auto_diff(function = div_scalar, eval_point = [a])
    assert(t3.val == 1)
    assert(t3.der['a'] == 1/3)

    t4 = Diff().auto_diff(function = div_function, eval_point = [a])
    assert(t4.val == 2)
    assert(t4.der['a'] == -1/3)

    t5 = Diff().auto_diff(function = simple_op_complete, eval_point = [a])
    assert(t5.val == 13)
    assert(t5.der['a'] == 9)

    # Unary
    t6 = Diff().auto_diff(function = unary, eval_point = [a])
    assert(t6.val == 6)
    assert(t6.der['a'] == 2)

    # Eq and ne
    assert(a == b)
    assert(a != c)
    assert(a != 3)
    assert(a == a)
    assert((a == 3) == False)
    assert((a != b) == False)

# More advanced operators
def power_scalar(x):
    return 10+x**2

def sqrt_scalar(x):
    return 10 + bm.sqrt(2*x+1)

def power_function(x):
    return 2**x

def power_function_general(x):
    return x**x

def test_more_operators():
    a = Variable(val=4, name='a')
    # Power
    t1 = Diff().auto_diff(function = power_scalar, eval_point = [a])
    assert(t1.val == 26)
    assert(t1.der['a'] == 8)

    # Square root
    t2 = Diff().auto_diff(function = sqrt_scalar, eval_point = [a])
    assert(t2.val == 13)
    assert(t2.der['a'] == 1/3)

    # Power function
    t3 = Diff().auto_diff(function = power_function, eval_point = [a])
    assert(t3.val == 16)
    assert(t3.der['a'] == bm.log(2)*16)
    assert(t3.der['a'] == np.log(2)*16)

    # Power function general
    t4 = Diff().auto_diff(function = power_function_general, eval_point = [a])
    assert(t4.val == 256)
    assert(t4.der['a'] == 256*(bm.log(4)+1))
    assert(t4.der['a'] == 256*(np.log(4)+1))

# Trig Functions
def sin_cos(x):
    return bm.sin(x) + bm.cos(x)

def tan_function(x):
    return bm.tan(2*x)

def inverse_trig(x):
    # arcsin, arccos, arctan
    return bm.arcsin(x) - bm.arccos(x) + bm.arctan(x)

def test_trig():
    a = Variable(val=0, name='a')
    # Sine and cosine
    t1 = Diff().auto_diff(function = sin_cos, eval_point = [a])
    assert(t1.val == 1)
    assert(t1.der['a'] == 1)

    # Tan
    t2 = Diff().auto_diff(function = tan_function, eval_point = [a])
    assert(t2.val == 0)
    assert(t2.der['a'] == 2)

    # Arcsin, arccos, arctan
    t3 = Diff().auto_diff(function = inverse_trig, eval_point = [a])
    assert(np.abs(t3.val + np.pi/2) < epsilon)
    assert(t3.der['a'] > 0)

# Other functions
def log_exp_function(x):
    return bm.log(x) + bm.exp(x)

def logk_none(x):
    return bm.logk(x) + 40 - 40

def logk_e(x):
    return bm.logk(x, bm.exp(1))

def test_other_functions():
    a = Variable(val=1, name='a')

    t1 = Diff().auto_diff(function = log_exp_function, eval_point = [a])
    assert(t1.val == np.exp(1))
    assert(t1.der['a'] == np.exp(1) + 1)

    t2 = Diff().auto_diff(function = logk_none, eval_point = [a])
    assert(t2.val == 0)
    assert(t2.der['a'] == 1)

    a = Variable(10, name='a')
    t3 = Diff().auto_diff(function = logk_e, eval_point = [a])
    assert(t3.val == np.log(10))
    assert(t3.der['a'] == 0.1)

# Functions that could be problematic
def div_zero(x):
    return x/0

def test_problematic():
    a = Variable(val=2, name='a')
    with pytest.raises(ZeroDivisionError):
        t1 = Diff().auto_diff(function = div_zero, eval_point = [a])
    with pytest.raises(NotImplementedError):
        t1 = Diff().hessian(functions = [add_function], eval_points = [a])
    with pytest.raises(NotImplementedError):
        print(bm.arcsinh(1))
    with pytest.raises(NotImplementedError):
        print(bm.arccosh(1))
    with pytest.raises(NotImplementedError):
        print(bm.arctanh(1))

def test_sanity_checks():
    assert(bm.log(4.1) == np.log(4.1))
    assert(bm.exp(-10.1) == np.exp(-10.1))
    assert(bm.sqrt(112.3) == np.sqrt(112.3))
    assert(bm.sin(4.1) == np.sin(4.1))
    assert(bm.cos(2.2) == np.cos(2.2))
    assert(bm.tan(2) == np.tan(2.0))
    assert(bm.arcsin(0) == np.arcsin(0))
    assert(bm.arccos(0.2) == np.arccos(0.2))
    assert(bm.arctan(2) == np.arctan(2))
    assert(bm.sinh(2) == np.sinh(2))
    assert(bm.cosh(2) == np.cosh(2))
    assert(bm.tanh(2) == np.tanh(2))
    assert(bm.logk(2, np.exp(1)) == np.log(2))

test_init()
test_simple_operators()
test_more_operators()
test_trig()
test_other_functions()
test_problematic()
test_sanity_checks()


import numpy as np
import pylab as pl

"""
rect - rectangular function
Inputs:
val : y-value of the rectangular function.
start : time (x-value) to start sampling from.
stop : time (x-value) to stop sampling.
(REQUIRE start <= stop)
rise : where the y-value of the rectangular function starts being non-zero.
fall : where the y-value of the rectangular function returns to zero.
(REQUIRE rise <= fall)
numpts = number of sampling points.

Outputs:
t = array containing all 'numpts' sampling times within start and stop.
h = array containing all values of the rectangular function whose value equals
'val' if the corresponding value in array t is within start and stop.
deltat = time interval between each sampling time.
"""
def rect(val, start, stop, rise, fall, numpts):
    t = np.linspace(start, stop, numpts, dtype=float)
    h = np.zeros_like(t)
    deltat = (stop - start) / (numpts-1.) # Sampling time interval
    for i in np.arange(0, len(t)):
        if t[i] >= rise and t[i] <= fall: # Within rectangle
            h[i] = val
    return t, h, deltat

"""
Gauss - Gaussian function
Inputs:
start : time (x-value) to start sampling from.
stop : time (x-value) to stop sampling.
(REQUIRE start <= stop)
numpts : number of sampling points.

Outputs:
t : array containing all 'numpts' sampling times within start and stop.
g : array containing all values of the Gaussian function given by g(t) =
1/sqrt(2*pi)*e^(-t^2/2)
deltat = time interval between each sampling time.
"""
def Gauss(start, stop, numpts):
    t = np.linspace(start, stop, numpts, dtype=float)
    deltat = (stop - start) / (numpts-1) # Sampling time interval
    g = 1./np.sqrt(2*np.pi)*np.exp(-t**2 / 2)
    return t, g, deltat

"""
conv - Convolution function
Inputs:
g : array containing the x-values of function (g).
h : array containing the x-values of function (h).
(REQUIRE sizes of g and h match)
deltat = time interval between each sampling time (this should match for both functions).

Optional inputs:
plotftg = False: whether to plot the FT form of the first function (g).
plotfth = False: whether to plot the FT form of the second function (h).
plotftcon = False: whether to plot the FT form of the convolution.

Output:
con : array containing the y-values of the convoluted function in time domain.
"""
def conv(t, g, h, deltat, plotftg = False, plotfth = False, plotftcon = False):
    hf = np.fft.fft(h)
    gf = np.fft.fft(g)
    freq = np.fft.fftfreq(h.size, d=deltat)
    if plotfth == True:
        pl.figure()
        pl.plot(freq, np.abs(hf)) # Magnitude used as the values are complex
        pl.title("Fourier transform of function 2 (h)")
    if plotftg == True:
        pl.figure()
        pl.plot(freq, np.abs(gf))
        pl.title("Fourier transform of function 1 (g)")
    conf = gf * hf
    if plotftcon == True:
        pl.figure()
        pl.plot(freq, np.abs(conf))
        pl.title("Fourier transform of the convoluted function (g*h)")
    con = np.abs(np.fft.ifft(conf))*deltat # When the FT is performed,
    # a normalisation factor deltat was divided for both g and h. However, the
    # inverse was only done once, so only one factor of deltat has been multiplied.
    # To normalise the inverse FT we need to multiply by deltat again.
    return con


import numpy as np

class SEFRClassifier:
    def __init__(self):
        self.weights = []
        self.bias = 0

    def fit(self, train_predictors, train_target):
        """
        This is used for training the classifier on data.
        Parameters
        ----------
        train_predictors : float, either list or numpy array
            are the main data in DataFrame
        train_target : integer, numpy array
            labels, should consist of 0s and 1s
        """
        X = train_predictors
        X = np.array(train_predictors, dtype="float32")

        self.y = train_target
        self.y = np.array(train_target, dtype="int32")

        # pos_labels are those records where the label is positive
        # neg_labels are those records where the label is negative
        pos_labels = np.sign(self.y) == 1
        neg_labels = np.invert(pos_labels)

        # pos_indices are the data where the labels are positive
        # neg_indices are the data where the labels are negative
        pos_indices = X[pos_labels, :]
        neg_indices = X[neg_labels, :]

        # avg_pos is the average value of each feature where the label is positive
        # avg_neg is the average value of each feature where the label is negative
        avg_pos = np.mean(pos_indices, axis=0)  # Eq. 3
        avg_neg = np.mean(neg_indices, axis=0)  # Eq. 4

        # weights are calculated based on Eq. 3 and Eq. 4

        self.weights = (avg_pos - avg_neg) / (avg_pos + avg_neg + 0.0000001)  # Eq. 5

        # For each record, a score is calculated. If the record is positive/negative, the score will be added to posscore/negscore
        sum_scores = np.dot(X, self.weights)  # Eq. 6

        pos_label_count = np.count_nonzero(self.y)
        neg_label_count = self.y.shape[0] - pos_label_count

        # pos_score_avg and neg_score_avg are average values of records scores for positive and negative classes
        pos_score_avg = np.mean(sum_scores[self.y == 1])  # Eq. 7
        neg_score_avg = np.mean(sum_scores[self.y == 0])  # Eq. 8

        # bias is calculated using a weighted average

        self.bias = (neg_label_count * pos_score_avg + pos_label_count * neg_score_avg) / (neg_label_count + pos_label_count)  # Eq. 9

    def predict(self, test_predictors):
        """
        This is for prediction. When the model is trained, it can be applied on the test data.
        Parameters
        ----------
        test_predictors: either list or ndarray, two dimensional
            the data without labels in
        Returns
        ----------
        predictions in numpy array
        """
        X = test_predictors
        if isinstance(test_predictors, list):
            X = np.array(test_predictors, dtype="float32")

        temp = np.dot(X, self.weights)
        self.preds = np.where(temp <= self.bias, 0 , 1)
        return self.preds

    # Calculate accuracy percentage between two lists
    def score(self,y, preds):
        correct = 0
        for i in range(len(y)):
            if y.array[i] == preds[i]:
                correct += 1
        return correct / float(len(y)) * 100.0

    def get_params(self,deep=False):
        return { }


from itertools import product
from sympy import symbols, exp, log
from sympy.codegen.numpy_nodes import logaddexp

x, y, z = symbols('x y z')

def test_logaddexp():
    lae_xy = logaddexp(x, y)
    ref_xy = log(exp(x) + exp(y))
    for wrt, deriv_order in product([x, y, z], range(0, 3)):
        assert (
            lae_xy.diff(wrt, deriv_order) -
            ref_xy.diff(wrt, deriv_order)
        ).rewrite(log).simplify() == 0

    one_third_e = 1*exp(1)/3
    two_thirds_e = 2*exp(1)/3
    logThirdE = log(one_third_e)
    logTwoThirdsE = log(two_thirds_e)
    lae_sum_to_e = logaddexp(logThirdE, logTwoThirdsE)
    assert lae_sum_to_e.rewrite(log) == 1
    assert lae_sum_to_e.simplify() == 1
    assert logaddexp(2, 3).simplify() == logaddexp(2, 3)  # cannot simplify with 2, 3


import numpy as np

from coptim.optimizer import Optimizer

class GradientMethod(Optimizer):
    def __init__(self):
        # TODO: More metrics: vector of x's, objective values, etc.
        self.iterations = 0

    def optimize(self, x_0, func, beta, sigma, epsilon):
        x = x_0
        while self.stopping_criteria(x, func, epsilon):
            descent_direction = -1 * func.gradient(x)

            step_size = self.step_size(x,
                                       func,
                                       beta,
                                       descent_direction,
                                       sigma)

            # update step
            x = x + step_size * descent_direction
            self.iterations += 1

        return x

    def stopping_criteria(self, x, func, epsilon):
        return np.linalg.norm(func.gradient(x)) >= epsilon

    def step_size(self, x, func, beta, d, sigma):
        i = 0
        inequality_satisfied = True
        while inequality_satisfied:
            if func.eval(x + np.power(beta, i) * d) <= func.eval(x) + np.power(beta, i) * sigma * func.gradient(x).dot(d):
                break

            i += 1

        return np.power(beta, i)


#!/usr/bin/env python3
import numpy as np
import matplotlib.pyplot as plt

def abline(slope, intercept):
    """Plot a line from slope and intercept"""
    axes = plt.gca()
    x_vals = np.array(axes.get_xlim())
    y_vals = intercept + slope * x_vals
    plt.plot(x_vals, y_vals, '--')

def main():
    n = int(input("Enter number of data points"))

    X = []
    Y = []
    for i in range(n):
        txt = "Enter the {value}th example in the training set."
        xi, yi = input(txt.format(value=i)).split()

        X.append(int(xi))
        Y.append(int(yi))

    print("The dataset contains the values")
    print(X)
    print(Y)

    sumX, sumX2, sumY, sumXY = 0, 0, 0, 0

    for i in range(0, n):
        sumX = sumX + X[i]
        sumX2 = sumX2 + (X[i] * X[i])

        sumY = sumY + Y[i]
        sumXY = sumXY + (X[i] * Y[i])

    m = ((n * sumXY) - (sumX * sumY))/((n*sumX2) - (sumX*sumX))
    c = (sumY - m * sumX)/n

    print("y = mx + c with c and m values respectively are:")
    print(c, m)

    plt.scatter(X, Y)
    abline(m, c)

    plt.show()

if __name__ == '__main__':
    main()


#-----------------------------------------------------------------------
# Program for studying the relation between the discrete cosine
# transform and the discrete fourier transform.
# Written by Maria Magnusson 2003-05-04
# Updated by Maria Magnusson 2007-04-30
# Ported to Python by Michael Felsberg 2016-03-01
#-----------------------------------------------------------------------

import numpy as np
from matplotlib import pyplot as plt
import cv2
a = np.load('images/goldhill128.npy')			# inimage
N = 128						# inimage size
b = np.vstack((np.hstack((a, a[:,::-1])), np.hstack((a[::-1,:], a[::-1,::-1]))))
# mirror inimage
u, v = np.meshgrid(np.arange(-N,N),np.arange(-N,N))
# (u,v) coordinate system

# factors to compensate for translation in the spatial domain
Ev = np.exp(-0.5j*v*np.pi/N)
Eu = np.exp(-0.5j*u*np.pi/N)

A = cv2.dct(a)					# discrete cosine transform

AA = np.fft.fftshift(np.fft.fft2(a))		# FFT
AA = AA/N;                              	# extra scaling

B = np.fft.fftshift(np.fft.fft2(b))		# fft + weighting
B = B*Ev*Eu
B[N,:] = B[N,:]/np.sqrt(2)
B[:,N] = B[:,N]/np.sqrt(2)
B = B/(2*N)
imagB = np.max(np.imag(B))			# check that imag part is 0
B = np.real(B)

# image limits
IMLIM = (0, np.max(a))
lim = np.max(A)/100
FLIM = (0, lim)

# show inimage, its FFT and its DCT
plt.figure(8)
plt.subplot(221), plt.imshow(a, 'gray', clim=IMLIM)
plt.title('original image, a(x,y)'), plt.colorbar()
plt.subplot(222), plt.imshow(np.abs(AA), 'gray', clim=FLIM)
plt.title('AA(u,v) = abs(FFT[a(x,y)])'), plt.colorbar()
plt.subplot(223), plt.imshow(np.abs(A), 'gray', clim=FLIM)
plt.title('A(u,v) = abs(DCT[a(x,y)])'), plt.colorbar()

# show inimage and mirrored inimage
# show fft + weighting of mirrored inimage and show lower right part
plt.figure(9)
plt.subplot(221), plt.imshow(a, 'gray', clim=IMLIM)
plt.title('original image, a(x,y)'), plt.colorbar()
plt.subplot(222), plt.imshow(b, 'gray', clim=IMLIM)
plt.title('mirrored image, b(x,y)'), plt.colorbar()
plt.subplot(223), plt.imshow(np.abs(B), 'gray', clim=FLIM)
plt.title('B(u,v) = almost abs(FFT[b(x,y)])'), plt.colorbar()
BPART = B[N:,N:]
plt.subplot(224), plt.imshow(np.abs(BPART), 'gray', clim=FLIM)
plt.title('lower right part of B(u,v)'), plt.colorbar()
plt.show()

print(f"Maximum difference: {np.max(A-BPART)}")	    	   	 # check that they are equal


import matplotlib
matplotlib.rcParams = matplotlib.rc_params_from_file('../../matplotlibrc')

import numpy as np
import math
import matplotlib.pyplot as plt
from scipy.stats import norm
from scipy.stats import invgamma
from scipy.stats import gaussian_kde

def mean_posterior(data, mu_0, sigma2_0, variance):
    n = float(len(data))
    sample_mean = np.mean(data)
    posterior_mean = ((mu_0*variance)/n + sample_mean*sigma2_0)/(
        variance/n + sigma2_0)
    posterior_variance = 1/(n/variance + 1/sigma2_0)
    return posterior_mean, posterior_variance

def variance_posterior(data, alpha, beta, mean):
    n = float(len(data))
    posterior_alpha = alpha + n/2.
    posterior_beta = beta + np.dot(data-mean, data-mean)/2.
    return posterior_alpha, posterior_beta

def sweep(sigma2, mu_0, sigma2_0, alpha, beta, data):
    posterior_mean, posterior_variance = mean_posterior(
        data, mu_0, sigma2_0, sigma2)
    mu = norm.rvs(posterior_mean, scale=np.sqrt(posterior_variance))
    posterior_alpha, posterior_beta = variance_posterior(data, alpha, beta, mu)
    sigma2 = invgamma.rvs(posterior_alpha, scale=posterior_beta)
    return mu, sigma2

def gibbs(data, sigma2, mu_0, sigma2_0, alpha, beta, n_samples=1000):
    mu_samples = np.zeros(n_samples)
    sigma2_samples = np.zeros(n_samples)
    for i in xrange(n_samples):
        mu, sigma2 = sweep(sigma2, mu_0, sigma2_0, alpha, beta, data)
        mu_samples[i] = mu
        sigma2_samples[i] = sigma2
    return mu_samples, sigma2_samples

def figures():
    data = np.genfromtxt('examscores.csv')

    sigma2 = 25.
    mu_0 = 80.
    sigma2_0 = 16.
    alpha = 3.
    beta = 50.
    mu_samples, sigma2_samples = gibbs(data, sigma2, mu_0, sigma2_0, alpha, beta)

    mukernel = gaussian_kde(mu_samples)

    x_min = min(mu_samples) - 1.
    x_max = max(mu_samples) + 1.
    x = np.arange(x_min, x_max, step=.1)
    plt.plot(x, mukernel(x))
    plt.savefig("mu_posterior.pdf")
    plt.clf()

    sigma2kernel = gaussian_kde(sigma2_samples)

    x_min = min(sigma2_samples) - 1.
    x_max = max(sigma2_samples) + 1.
    x = np.arange(x_min, x_max, step=1.)
    plt.plot(x, sigma2kernel(x))
    plt.savefig("sigma2_posterior.pdf")
    plt.clf()

    score_samples = np.array([norm.rvs(mu_sample, np.math.sqrt(sigma2_sample))
                            for mu_sample, sigma2_sample in zip(mu_samples, sigma2_samples)])
    score_kernel = gaussian_kde(score_samples)
    x_min = min(score_samples) - 1.
    x_max = max(score_samples) + 1.
    plt.plot(x, score_kernel(x))
    plt.savefig("predictiveposterior.pdf")

figures()


"""
Задача 4:
Найти в массиве те элементы, значение которых меньше среднего арифметического, взятого от
всех элементов массива.
"""
from random import randint

import numpy as np

def main():
    try:
        n = int(input("Введите кол-во строк в матрице -> "))
        m = int(input("Введите кол-во столбцов в матрице -> "))
    except ValueError:
        print("Некорректный ввод данных!")
        return

    # Генерация данных
    matrix = np.matrix([[randint(-100, 100) for x in range(m)] for y in range(n)])
    print("Сгенерированная матрица:\n", matrix)
    mean = np.mean(matrix)
    print("Среднее арифметическое: {}".format(mean))
    for e in np.nditer(matrix):
        if e < mean:
            print("Элемент {} меньше сред. арифметического".format(e))

if __name__ == "__main__":
    main()


import numpy as np
import tensorflow as tf
import random
import matplotlib.pyplot as plt
from gm_generate import *

class IntermediateExample1(object):
	"""
		Class implementing variational inference for 1D gaussian data by using monte-carlo approximation to ELBO
	"""

	def __init__(self, mu_p=0.0, sigma_p=1.0, mu_var_p=0.0, sigma_var_p=1.0, learning_rate=1e-4, K=1, N=100):
		"""
			__init__(IntermediateExample1, float, float, float, float, float, int, int) -> None
			mu_p: Hyperparamer for p(mu)
			sigma_p: Hyperparameter for p(mu)
			mu_var_p: Hyperparameter for p(sigma)
			sigma_var_p: Hyperparameter for p(sigma)
			learning_rate: Learning rate for optimizer
			K: Number of samples used for Monte-Carlo approximation of ELBO
			N: Number of examples per batch
		"""
		self.N = N
		self.x = tf.placeholder(tf.float32, (self.N,))
		self.mu_p = mu_p
		self.sigma_p = sigma_p
		self.mu_var_p = mu_var_p
		self.sigma_var_p = sigma_var_p
		self.learning_rate = learning_rate
		self.K = K

		# Initialize the variables
		self.sigma = tf.Variable(random.random())
		self.mu = tf.Variable(random.random())
		self.sigma_var = tf.Variable(random.random())
		self.mu_var = tf.Variable(random.random())

		# Generate K samples of z
		eps_samples = tf.random_normal(shape=(K,))	# Reparameterisation trick for normal
		mu_samples = self.mu + eps_samples*self.sigma**2
		eps_samples2 = tf.random_uniform(shape=(K,))	# Reparameterisation trick for exponential
		sigma_samples = (self.mu_var + eps_samples2*self.sigma_var**2) ** 2

		# Approximate ELBO (without constant term)
		self.ELBO = tf.reduce_mean(-(N/2.0) * tf.log(sigma_samples) - \
				0.5 * tf.reduce_sum((self.x - tf.stack([mu_samples]*N, axis=1))**2, axis=1) / sigma_samples - \
				0.5 * (mu_samples - self.mu_p)**2 / self.sigma_p**2 - \
				0.5 * (sigma_samples - self.mu_var_p)**2 / self.sigma_var_p**2 - \
				0.5 * tf.log(self.sigma**2) + \
				0.5 * (mu_samples - self.mu)**2 / self.sigma**2 + \
				0.5 * tf.log(self.sigma_var**2) + \
				0.5 * (sigma_samples - self.mu_var)**2 / self.sigma_var**2)

		self.ELBO = -self.ELBO

		# Maximize ELBO
		self.train = tf.train.AdamOptimizer(self.learning_rate).minimize(self.ELBO)

		# Set up the session
		self.sess = tf.InteractiveSession()
		self.sess.run(tf.global_variables_initializer())

	def train_step(self, x):
		"""
			train_step(IntermediateExample1, ndarray) -> (float, float, float, float, float)
			x: Input data, vector of real numbers

			Returns:
				cost: -ELBO after a step of optimization
				mu,	sigma, mu_var, sigma_var
		"""
		_, cost = self.sess.run([self.train, self.ELBO], feed_dict={self.x: x})
		mu, sigma, mu_var, sigma_var = self.sess.run([self.mu, self.sigma, self.mu_var, self.sigma_var])
		return (-cost, mu, sigma**2, mu_var, sigma_var**2)

def run_intermediate_example_1(num_examples=100, data_mu=0.0, data_sigma=1.0, mu_p=0.0, sigma_p=1.0, mu_var_p=0.0, sigma_var_p=1.0, learning_rate=1e-4, num_iter=1000, K=1, N=100):
	"""
		run_intermediate_example_1(int, float, float, float, float, float, float, float, float, int, int) -> None
		Runs the demo shown in the notebook for different settings of hyperparameters.
	"""
	# Generate the data
	pz = [1]
	mu = [np.asarray([data_mu])]
	sigma = [np.asarray([data_sigma]).reshape((1, 1))]
	gmm = GMM(pz=pz, muks=mu, sigmaks=sigma, k=1, d=1)
	x, _ = gmm.generate_points(n=num_examples)
	x = x.reshape((-1,))

	# Compute variational inference estimate for the parameters
	costs = []
	example = IntermediateExample1(mu_p, sigma_p, mu_var_p, sigma_var_p, learning_rate, K, N)
	for i in range(num_iter):
		cost, mu_ex, sigma_ex, mu_var, sigma_var = example.train_step(x)
		costs.append(cost)

	# Compute mu_expected, sigma_expected
	mu_expected = mu_ex # Expected value of mu using q_1
	sigma_expected = mu_var**2 # Expected value of sigma using q_2

	# Print results
	print 'Optimal m:', mu_ex
	print 'Optimal s^2:', sigma_ex
	print 'Optimal m var:', mu_var
	print 'Optimal s^2 var:', sigma_var
	print 'Expected Value for mu:', mu_expected
	print 'Optimal Value for sigma^2:', sigma_expected

	# Plot cost vs iterations
	plt.plot(costs)
	plt.title('Iteration vs ELBO')
	plt.xlabel('Iterations')
	plt.ylabel('ELBO')
	plt.show()

	# Show the histogram, true distribution and estimated distribution
	plt.hist(x, normed=True, color='#cccccc')
	def true_dist(x):
	   return (1.0/np.sqrt(2*np.pi*sigma[0])*np.exp(-0.5*((x-mu[0])/sigma[0])**2))
	def estimated_dist(x):
		return (1.0/np.sqrt(2*np.pi*sigma_expected)*np.exp(-0.5*((x-mu_expected)/sigma_expected)**2))
	x_axis = np.arange(np.min(x)-0.5, np.max(x)+0.5, 0.01)
	plt.plot(x_axis, true_dist(x_axis).reshape((-1,)), 'ro', label='True Distribution')
	plt.plot(x_axis, estimated_dist(x_axis).reshape((-1,)), 'co', label='Estimated Distribution')
	plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
	plt.show()

"""
if __name__ == '__main__':
	ex = IntermediateExample1(learning_rate=0.05)
	for i in range(1000):
		cost, mu, sigma, alpha, beta = ex.train_step(np.asarray([1.0, 2.0, 3.0]))
		print (cost, mu, sigma, alpha, beta)
"""