#not an application just a module

'''what is this program?
    Assume we have N points on a sphere. points are always pushing each other and they cannot leave surface of the sphere.
    After some play we will see the points in a state of equilibrium. If N > 3 points form a 3d solid.
    Interestingly we can have a solid with declaring N.(ofcourse they are specific type of solids)
    I wanted to study those solids. so we have this program which gives scatter plot of points of those solids.
    '''
#lessthan 20 points are feasible.
import numpy as np

def magnitude(lst):#takes a list of coordinates. Returns magnitude value of that position vector.
    return np.sqrt(lst[0]*lst[0]+lst[1]*lst[1]+lst[2]*lst[2])

def normalize(lst):#takes a list of coordinates. Returns a normalized version of it.
    mag = magnitude(lst)
    return np.array([lst[0]/mag,lst[1]/mag,lst[2]/mag])

def angle_bw(v1,v2): #takes two lists of coordinates of point. Returns angle in degrees
    #Dot product
    dot_product = (v1[0]*v2[0])+(v1[1]*v2[1])+(v1[2]*v2[2])
    #dodging math domain error. making dot product not to overflow from range [-1,1]
    if dot_product < -1:
        dot_product = -1
    elif dot_product > 1:
        dot_product = 1

    return (np.arccos(dot_product))*180/math.pi

def points_on_unit_sphere(N):
    #generating N points from specified range to get unique points
    #And shuffling points for randomness
    rectangular = np.array([np.random.permutation(np.linspace(1,10,N)),
    np.random.permutation(np.linspace(11,20,N)),
    np.random.permutation(np.linspace(21,30,N))])
    rectangular = np.transpose(rectangular)
    for i in range(N):
        rectangular[i] = normalize(rectangular[i])
    #force_vector to find direction of force form all other points
    force_vector = np.zeros(3)
    condition = True

    while condition:
        #in this loop:
        #for a point we find all vectors looking at the point.
        #Add them and normalize resultant vector.
        #Make that resultant unit vector as positional vector of the point.
        max_jump_distance = 0
        for i in range(N):
            force_vector = N*rectangular[i]-np.sum(rectangular,axis = 0)
            force_vector = normalize(force_vector)
            #here we make sure if points are stabalized or not
            jump_distance = magnitude(force_vector-rectangular[i])
            if jump_distance > max_jump_distance:
                max_jump_distance = jump_distance
            rectangular[i] = force_vector
            force_vector = np.zeros(3)
        if max_jump_distance < 0.0000000001:
            condition = False
    #returning finalized rectangular coordinates to plot them.
    return rectangular


# Kalman filter in Python adopted from http://scipy-cookbook.readthedocs.io/items/KalmanFiltering.html
import numpy as np
import matplotlib.pyplot as plt
import time

class KalmanFilter:
    def __init__(self, base_value=24, iterations=200, initial_guess=20.0, posteri_estimate=4.0, data=[], plot=False):
        # intial parameters
        self.n_iter = iterations  # How many iterations to create test data
        sz = (self.n_iter,)  # size of array
        self.x = base_value  # This is the base value that shall be used to create noisy data. It is the true value
        if len(data) == 0:
            self.z = np.random.normal(self.x, 1, size=sz)  # observations (normal about x, sigma=0.1)
        else:
            self.z = data

        self.Q = 1e-5 # process variance

        # allocate space for arrays
        self.xhat = np.zeros(sz)      # a posteri estimate of x
        self.P = np.zeros(sz)         # a posteri error estimate
        self.xhatminus = np.zeros(sz)  # a priori estimate of x
        self.Pminus = np.zeros(sz)

        # a priori error estimate
        self.K = np.zeros(sz)         # gain or blending factor

        self.R = 2

        # intial guesses
        self.xhat[0] = initial_guess  # Initial estimate
        self.P[0] = posteri_estimate  # Estimate of the error made

        self.plot = plot

    def filter(self):
        start = time.time()
        for k in range(1, self.n_iter):
            # time update
            self.xhatminus[k] = self.xhat[k-1]
            self.Pminus[k] = self.P[k-1]+self.Q

            # measurement update
            self.K[k] = self.Pminus[k]/(self.Pminus[k]+self.R)
            self.xhat[k] = self.xhatminus[k]+self.K[k]*(self.z[k]-self.xhatminus[k])
            self.P[k] = (1-self.K[k])*self.Pminus[k]
        end = time.time()

        print("Took %s seconds" % (time.time() - start))

        print "Noisy data: "
        print self.z

        print "Estimates:"
        print self.xhat

        print "Truth Value:"
        print self.x

        #print "Error estimate"
        #print self.P

        if self.plot:
            plt = self.plot_results()
        else:
            plt = None

        return self.z, self.xhat, self.x, plt

    def plot_results(self):
        plt.rcParams['figure.figsize'] = (10, 8)
        plt.figure()
        plt.plot(self.z, 'k+', label='noisy measurements')
        plt.plot(self.xhat, 'b-', label='a posteri estimate')
        plt.axhline(self.x, color='g', label='truth value')
        plt.legend()
        plt.title('Estimate vs. iteration step', fontweight='bold')
        plt.xlabel('Iteration')
        plt.ylabel('Temperature')

        return plt


from matplotlib import pyplot as plt

import numpy as np

# numpy's fft implementation is slow, so use FFTW as a drop-in replacement
import pyfftw.interfaces.numpy_fft as fft

from math import floor

# Load an image
image = plt.imread("einstein1_7.jpg")

# Make image greyscale
image = np.average(image, axis=2)

# Set up geometry
width, height = image.shape

centre_x = floor(width) / 2
centre_y = floor(height) / 2

x_axis = np.arange(width)
y_axis = np.arange(height)

# Create circular filter
filter_radius = 100
filter = np.zeros_like(image)

for i in range(width):
    for j in range(height):
        if (i - centre_x) ** 2 + (j - centre_y) ** 2 > filter_radius ** 2:
            filter[i, j] = 1

# Invert: lowpass filter
filter = 1 - filter

# Move to Fourier plane
FT = fft.fftshift(fft.fft2(image))

# Apply Fourier filter
filtered_FT = FT * filter

# Inverse Fourier transform to image plane
filtered_image = fft.ifft2(fft.ifftshift(filtered_FT))

# Plot results
plt.figure(figsize=[20, 20])

# Original image
plt.subplot(2, 2, 1)
plt.title("Original image")
plt.imshow(image)

# Fourier transform; log scale to bring out detail outside centre
plt.subplot(2, 2, 2)
plt.title("Fourier transform of original image")
plt.imshow(np.log(np.abs(FT) ** 2))

# Filtered fourier transform
plt.subplot(2, 2, 3)
plt.title("Fourier transform restricted to leading modes")
plt.imshow(np.log(np.abs(filtered_FT) ** 2))

# Observed image
plt.subplot(2, 2, 4)
plt.title("Observed image with filter")
plt.imshow(np.abs(filtered_image) ** 2)

plt.savefig("fourier_restricted.pdf")

def salt_pepper(image, r):
    '''Add random light and dark pixels with frequency `r` to `image`,
    returning the result.'''

    r = min(1, r)
    uniform_random = np.random.random(image.shape)

    # Pepper
    noisy_image = np.where(uniform_random < r / 2,
                           np.zeros_like(image),
                           image)

    # Salt
    noisy_image = np.where(uniform_random > 1 - r / 2,
                           np.ones_like(image) * 255,
                           noisy_image)
    return noisy_image

# Add noise to image
noisy_image = salt_pepper(image, 0.1)

# Reuse filter from previous task
lowpass_filter = 1 - filter

# Move to Fourier plane
FT = fft.fftshift(fft.fft2(noisy_image))

# Apply Fourier filter
filtered_FT = FT * lowpass_filter

# Inverse Fourier transform to image plane
filtered_image = fft.ifft2(fft.ifftshift(filtered_FT))

# Plot results
plt.figure(figsize=[15, 15])

# Original image
plt.subplot(2, 2, 1)
plt.title("Image with noise added")

# White noise doesn't show up very well with the default colour map
plt.imshow(noisy_image, cmap='gray')

# Fourier transform; log scale to bring out detail outside centre
plt.subplot(2, 2, 2)
plt.title("Fourier transport of noisy image")
plt.imshow(np.log(np.abs(FT) ** 2))

# Filtered fourier transform
plt.subplot(2, 2, 3)
plt.title("Fourier transform with leading-order modes filtered out")
plt.imshow(np.log(np.abs(filtered_FT) ** 2))

# Observed image
plt.subplot(2, 2, 4)
plt.title("Observed image, noise only")
plt.imshow(np.abs(filtered_image) ** 2 / np.max(abs(filtered_image) ** 2),
           cmap='gray')

plt.savefig("noise_isolation.pdf")

# Move to Fourier plane
FT = fft.fftshift(fft.fft2(image))

# Remove phase information in Fourier plane
phaseless_image = fft.ifft2(fft.ifftshift(abs(FT) ** 2))

# Plot results
plt.figure(figsize=[15, 15])

# Original image
plt.subplot(2, 2, 1)
plt.title("Original image")
plt.imshow(image, cmap='gray')

# Phaseless image
plt.subplot(2, 2, 2)
plt.title("Phaseless image")
plt.imshow(abs(phaseless_image) ** 2)

plt.savefig("phase_contrast.pdf")


import numpy as np
import plotly.graph_objects as go

# rotate about y, translate in x
def frame_yrotate_xtranslate(theta, x):
  theta = np.radians(theta)
  cos_theta = np.cos(theta)
  sin_theta = np.sin(theta)

  return np.array([
    [cos_theta, 0, sin_theta, x],
    [0, 1, 0, 0],
    [-sin_theta, 0, cos_theta, 0],
    [0, 0, 0, 1]
  ])

# rotate about z, translate in x and y
def frame_zrotate_xytranslate(theta, x, y):
  theta = np.radians(theta)
  cos_theta = np.cos(theta)
  sin_theta = np.sin(theta)

  return np.array([
    [cos_theta, -sin_theta, 0, x],
    [sin_theta, cos_theta, 0, y],
    [0, 0, 1, 0],
    [0, 0, 0, 1]
  ])

class Point:
  def __init__(self, x, y, z):
    self.x = x
    self.y = y
    self.z = z

  def get_point_wrt(self, reference_frame):
    # given frame_ab which is the pose of frame_b wrt frame_a
    # given a point as defined wrt to frame_b
    # return point defined wrt to frame a
    p = np.array([self.x, self.y, self.z, 1])
    p = np.matmul(reference_frame, p)
    return Point(p[0], p[1], p[2])

class Linkage:
  def __init__(self, a, b, c, alpha=0, beta=0, gamma=0, new_x_axis=0, new_origin=Point(0, 0, 0)):
    self.store_linkage_attributes(a, b, c, new_x_axis, new_origin)
    self.save_new_pose(alpha, beta, gamma)

  def store_linkage_attributes(self, a, b, c, new_x_axis, new_origin):
    self._a = a
    self._b = b
    self._c = c
    self._new_origin = new_origin
    self._new_x_axis = new_x_axis

  def save_new_pose(self, alpha, beta, gamma):
    self._alpha = alpha
    self._beta = beta
    self._gamma = gamma

    # frame_ab is the pose of frame_b wrt frame_a
    frame_01 = frame_yrotate_xtranslate(theta=-self._beta, x=self._a)
    frame_12 = frame_yrotate_xtranslate(theta=90-self._gamma, x=self._b)
    frame_23 = frame_yrotate_xtranslate(theta=0, x=self._c)

    frame_02 = np.matmul(frame_01, frame_12)
    frame_03 = np.matmul(frame_02, frame_23)
    new_frame = frame_zrotate_xytranslate(self._new_x_axis + self._alpha, self._new_origin.x, self._new_origin.y)

    # find points wrt to body contact point
    p0 = Point(0, 0, 0)
    p1 = p0.get_point_wrt(frame_01)
    p2 = p0.get_point_wrt(frame_02)
    p3 = p0.get_point_wrt(frame_03)

    # find points wrt to center of gravity
    self.p0 = self._new_origin
    self.p1 = p1.get_point_wrt(new_frame)
    self.p2 = p2.get_point_wrt(new_frame)
    self.p3 = p3.get_point_wrt(new_frame)

  def change_pose(self, alpha=None, beta=None, gamma=None):
    if alpha is None:
      alpha = self._alpha
    if beta is None:
      beta = self._beta
    if gamma is None:
      gamma = self._gamma
    self.save_new_pose(alpha, beta, gamma)

class Hexagon:
  def __init__(self, f, m, s):
    self.f = f
    self.m = m
    self.s = s

    self.cog = Point(0, 0, 0)
    self.head = Point(0, s, 0)
    self.vertices = [
      Point(m, 0, 0),
      Point(f, s, 0),
      Point(-f, s, 0),
      Point(-m, 0, 0),
      Point(-f, -s, 0),
      Point(f, -s, 0),
    ]

    self.new_x_axes = [
      0, 45, 135, 180, 225, 315
    ]

class VirtualHexapod:
  def __init__(self, a=0, b=0, c=0, f=0, m=0, s=0):
    self.linkage_measurements = [a, b, c]
    self.body_measurements = [f, m, s]
    self.body = Hexagon(f, m, s)
    self.store_neutral_legs(a, b, c)

  def store_neutral_legs(self, a, b, c):
    self.legs = []
    for point, theta in zip(self.body.vertices, self.body.new_x_axes):
      linkage = Linkage(a, b, c, new_x_axis=theta, new_origin=point)
      self.legs.append(linkage)

class VirtualHexapodPlot:
  def __init__(self, _hexapod):
    self.hexapod = _hexapod
    self.fig = go.Figure()

  def _draw_lines(self, _name, _points, _size, _color, _is_name_visible=True):
    self.fig.add_trace(go.Scatter3d(
      name=_name,
      x=[point.x for point in _points],
      y=[point.y for point in _points],
      z=[point.z for point in _points],
      line={
        'color': _color,
        'width': _size
      },
      showlegend=_is_name_visible
    ))

  def _draw_point(self, _name, _point, _size, _color):
    self.fig.add_trace(go.Scatter3d(
      name=_name,
      x=[_point.x],
      y=[_point.y],
      z=[_point.z],
      mode='markers',
      marker={
        'size': _size,
        'color': _color,
        'opacity': 1.0
      }
    ))

  def draw(self):
    LINE_SIZE = 10
    HEAD_SIZE = 15
    COG_SIZE = 10
    BODY_COLOR = '#8e44ad'
    COG_COLOR = '#e74c3c'
    LEG_COLOR = '#2c3e50'

    # Add body outline
    points = self.hexapod.body.vertices
    self._draw_lines('body', points + [points[0]], LINE_SIZE, BODY_COLOR)

    # Add head and center of gravity
    self._draw_point('cog', self.hexapod.body.cog, COG_SIZE, COG_COLOR)
    self._draw_point('head', self.hexapod.body.head, HEAD_SIZE, BODY_COLOR)

    # Draw legs
    for leg in self.hexapod.legs:
      points = [leg.p0, leg.p1, leg.p2, leg.p3]
      self._draw_lines('leg', points, LINE_SIZE, LEG_COLOR, False)

    self.fig.show()

FRONT_LENGTH = 20
SIDE_LENGTH = 30
MID_LENGTH = 40
HIP_LENGTH = 25
KNEE_LENGTH = 40
ANKLE_LENGTH = 60

virtual_hexapod = VirtualHexapod(HIP_LENGTH, KNEE_LENGTH, ANKLE_LENGTH, FRONT_LENGTH, MID_LENGTH, SIDE_LENGTH)
VirtualHexapodPlot(virtual_hexapod).draw()


import numpy as np
import matplotlib.pyplot as plt

def hough(points, weights = None, discretizationRadius = 1000, discretizationAngle = 180):
    """
        Computes hough transforms of the points (in 2D)

        Arguments:
            points {Array n * 2} -- Datapoints to represent in Hough Space
            weights {Array n} -- Weights to associate to each points
                (default {None} - Equal weights)
            discretizationRadius {Int} -- Discretization radius Axis
            discretizationAngle {Int} -- Discretization Angle Axis
    """
    # Polar coordinate of all points
    r = np.sqrt(points[:,0]**2 + points[:,1]**2)
    theta = np.arctan2(points[:,1], points[:,0])

    # Hough space
    houghSpace = np.zeros((discretizationRadius, discretizationAngle))
    radiusBins = np.linspace(- np.max(r), np.max(r), discretizationRadius + 1)
    angleBins = np.linspace(-np.pi, np.pi, discretizationAngle)
    for i, phi in enumerate(angleBins):
        # For the given theta compute the radius of the line cutting the points
        radPhi = np.cos(phi - theta) * r
        hist, _ = np.histogram(radPhi, bins = radiusBins, weights = weights)
        houghSpace[:, i] += hist

    return np.flip(houghSpace, 0), angleBins * 180 / np.pi, radiusBins

def displayHough(points, weights = None):
    """
        Computes hough transforms of the points and displays it

        Arguments:
            points -- Datapoints to project and anlyze
            weights {Array n} -- Weights to associate to each points
    """
    houghSpace, xaxis, yaxis = hough(points, weights)

    plt.figure()
    plt.imshow(houghSpace, extent=[xaxis[0], xaxis[-1], yaxis[0], yaxis[-1]], aspect='auto', cmap='gray')
    plt.ylabel("Radius")
    plt.xlabel("Angle(in deg)")
    plt.show()


from argparse import ArgumentParser

from sympy import diff, dsolve, integrate, solve, var

from .abstract_problem import AbstractSolver
from .utils import sympy_eval, t, x, x_diff

class SimplestSolver(AbstractSolver):

    """
    Solver for simplest problem in calculus of variation.

    Attributes:
        L: Integrand.
        t0: Lower limit of the integral.
        t1: Upper limit of the integral.
        x0: Boundary condition in t0.
        x1: Boundary condition in t1.

    To use:
        solution = SimplestSolver(L="x_diff ** 2", t0="0", t1="1", x0="0", x1="1")
        solution.solve(verbose=True)
    """

    C1 = var("C1")
    C2 = var("C2")

    def __init__(self, L: str, t0: str, t1: str, x0: str, x1: str):
        self._L_str = L

        self.L = sympy_eval(L)
        self.t0 = sympy_eval(t0)
        self.t1 = sympy_eval(t1)
        self.x0 = sympy_eval(x0)
        self.x1 = sympy_eval(x1)

    def __str__(self):
        task = f"integral from {self.t0} to {self.t1} of ({self._L_str})dt -> extr\n"
        condition_1 = f"x({self.t0}) = {self.x0}\n"
        condition_2 = f"x({self.t1}) = {self.x1}\n"
        return f"{task}{condition_1}{condition_2}"

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

    def _general_solution(self):
        """
        Find general solution.
        """

        self.L_x_diff = diff(self.L, x_diff)
        self.L_x = diff(self.L, x)

        general_solution = dsolve(self.L_x - diff(self.L_x_diff, t), x).rhs.expand()
        self.general_solution = general_solution

    def _coefficients(self):
        """
        Find particular solution coefficients.
        """

        self.first_eq = self.general_solution.subs(t, self.t0) - self.x0
        self.second_eq = self.general_solution.subs(t, self.t1) - self.x1

        coefficients = solve([self.first_eq, self.second_eq], [self.C1, self.C2])
        self.coefficients = coefficients

    def _particular_solution(self):
        """
        Substitute particular solution coefficients to general solution.
        """

        super()._particular_solution()

    def _extrema_value(self):
        """
        Find extrema value for particular solution.
        """

        L_subs = self.L.subs(
            [(x_diff, diff(self.particular_solution, t)), (x, self.particular_solution)]
        )
        extrema_value = integrate(L_subs, (t, self.t0, self.t1))

        self.extrema_value = extrema_value

    def solve(self, verbose: bool = True):
        """
        Solve task using all encapsulated methods.
        """

        super().solve(verbose=verbose)

if __name__ == "__main__":

    # argparse
    parser = ArgumentParser()
    parser.add_argument("-L", type=str, required=True, help="integrand")
    parser.add_argument(
        "-t0", type=str, required=True, help="lower limit of the integral"
    )
    parser.add_argument(
        "-t1", type=str, required=True, help="upper limit of the integral"
    )
    parser.add_argument("-x0", type=str, required=True, help="boundary condition in t0")
    parser.add_argument("-x1", type=str, required=True, help="boundary condition in t1")
    args = parser.parse_args()

    # solve
    SimplestSolver(L=args.L, t0=args.t0, x0=args.x0, t1=args.t1, x1=args.x1).solve()


import numpy as np
import pytest

from phantomsetup import orbits

@pytest.mark.parametrize(
    'planet_radius, planet_mass, stellar_mass, eccentricity, r_hill_exact',
    [(1.0, 0.01, 1.0, 0.0, 0.149380158)],
)
def test_hill_sphere_radius(
    planet_radius, planet_mass, stellar_mass, eccentricity, r_hill_exact
):
    r_hill = orbits.hill_sphere_radius(
        planet_radius=planet_radius,
        planet_mass=planet_mass,
        stellar_mass=stellar_mass,
        eccentricity=eccentricity,
    )

    result = np.allclose(r_hill, r_hill_exact)
    assert result

@pytest.mark.parametrize(
    (
        'primary_mass, secondary_mass, semi_major_axis, eccentricity, '
        'pos1_exact, pos2_exact, vel1_exact, vel2_exact'
    ),
    [
        (
            1.0,
            1.0,
            1.0,
            0.0,
            [0, -0.5, 0],
            [0, 0.5, 0],
            [0.707106781, 0, 0],
            [-0.707106781, 0, 0],
        ),
        (
            1.0,
            1.0,
            1.0,
            0.5,
            [0, -0.25, 0],
            [0, 0.25, 0],
            [1.22474487, 0, 0],
            [-1.22474487, 0, 0],
        ),
    ],
)
def test_binary_orbit(
    primary_mass,
    secondary_mass,
    semi_major_axis,
    eccentricity,
    pos1_exact,
    pos2_exact,
    vel1_exact,
    vel2_exact,
):

    pos1, pos2, vel1, vel2 = orbits.binary_orbit(
        primary_mass, secondary_mass, semi_major_axis, eccentricity
    )

    result = np.allclose(pos1, pos1_exact)
    assert result
    result = np.allclose(pos2, pos2_exact)
    assert result
    result = np.allclose(vel1, vel1_exact)
    assert result
    result = np.allclose(vel2, vel2_exact)
    assert result

@pytest.mark.parametrize(
    'primary_mass, secondary_mass, periapsis_distance, pos1_exact, pos2_exact, '
    'vel1_exact, vel2_exact',
    [(1, 1, 10, [0, 0, 0], [60, -80, 0], [0, 0, 0], [-6.324555e-2, 1.8973666e-1, 0])],
)
def test_flyby_orbit(
    primary_mass,
    secondary_mass,
    periapsis_distance,
    pos1_exact,
    pos2_exact,
    vel1_exact,
    vel2_exact,
):

    pos1, pos2, vel1, vel2 = orbits.flyby_orbit(
        primary_mass, secondary_mass, periapsis_distance
    )

    result = np.allclose(pos1, pos1_exact)
    assert result
    result = np.allclose(pos2, pos2_exact)
    assert result
    result = np.allclose(vel1, vel1_exact)
    assert result
    result = np.allclose(vel2, vel2_exact)
    assert result

@pytest.mark.parametrize(
    'primary_mass, secondary_mass, periapsis_distance, gravitational_constant, '
    'time_exact',
    [(1.0, 1.0, 10.0, 1.0, 758.946638440411)],
)
def test_flyby_time(
    primary_mass, secondary_mass, periapsis_distance, gravitational_constant, time_exact
):
    time = orbits.flyby_time(
        primary_mass, secondary_mass, periapsis_distance, gravitational_constant
    )

    result = np.allclose(time, time_exact)
    assert result


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

def generate_zc_sequence(N, u):
    # Add a Zadoff-Chu sequence for
    n = np.arange(N)
    zadoff_chu_seq = np.exp(-1j * (np.pi * u * n * (n + (N % 2)))/N)

    return zadoff_chu_seq

if __name__ == "__main__":
    import matplotlib.pyplot as plt

    N = 353
    u = 73
    seq = generate_zc_sequence(N, u)
    fig, axes = plt.subplots(2, 1)
    axes[0].set_title('Zadoff Chu sequence, N = {}, u = {}'.format(N, u))
    axes[0].plot(seq.real)
    axes[0].set_ylabel('Real part')
    axes[1].plot(seq.imag)
    axes[1].set_ylabel('Imag part')

    plt.figure()
    autocorrelation = np.correlate(seq, seq, mode='same')
    plt.plot(autocorrelation)
    plt.title('Autocorrelation of Zadoff Chu sequence, N = {}, u = {}'.format(N, u))


import numpy as np
import matplotlib.pyplot as plt

g = 9.81
def analytical_p(h):
    return (1000 * h + h**2 / 2) * g

def rho(h):
    return 1000.0 + h

H = 400.0
N = 20

p = np.zeros(N)
dh = H / (N - 1)

for i in range(1, N):
    h = i * dh
    p[i] = p[i-1] + rho(h) * g * dh

print("%f"%p[N-1])
plt.gca().invert_yaxis()
height = np.linspace(0.0, H, N)

plt.plot(p, height, "o", label="Numerical", ms=8)
plt.plot(analytical_p(height), height, "-", lw=3, label="Analytical")

plt.xlabel("$p$", fontsize=20)
plt.ylabel("$h$", fontsize=20)

plt.grid()
plt.legend(loc="best")

plt.savefig("pressure.png")
plt.show()


import numpy as np
import math
from numpy.random import default_rng
from crisp.utils.planar_utils import radial_squared_error

def generate_circumference(center, radius, num_points):
    """
    Generates a circle trajectory
    :param center: coordinates of circumference center
    :param radius: circumference radius
    :param num_points: number of points in the trajectory
    :return: a ndarray with the trajectory of points
    """
    theta_z = np.linspace(0, 360, num=num_points)
    Circle = np.zeros((num_points, 3))
    Circle[:, 0] = center[0] + radius * np.cos(np.radians(theta_z))
    Circle[:, 1] = center[1] + radius * np.sin(np.radians(theta_z))
    Circle[:, 2] = center[2]

    return Circle

def generate_noisy_circumference_samples(center, radius1, radius2, num_points):
    """
    Generates a circle trajectory
    :param center: coordinates of circumference center
    :param radius1: Main circumference radius
    :param radius2: small torus radius
    :param num_points: number of points to sample
    :return: a ndarray with the trajectory of points
    """

    sample = np.zeros((num_points, 3))

    # Initialize random number generator
    rng = default_rng()

    for i in range(num_points):

        # Uniformly sample joint_ranges
        theta1 = rng.uniform(0, 2*np.pi, 1)
        theta2 = rng.uniform(0, 2*np.pi, 1)
        r = radius2*np.sqrt(rng.uniform(0, 1, 1))

        # Sample on main circumference
        sample[i, 0] = center[0] + radius1 * np.cos(theta1)
        sample[i, 1] = center[1] + radius1 * np.sin(theta1)
        sample[i, 2] = center[2]

        # Add torus noise (see https://stackoverflow.com/a/50746409)
        sample[i, 0] = sample[i, 0] + r * np.cos(theta2) * np.cos(theta1)
        sample[i, 1] = sample[i, 1] + r * np.cos(theta2) * np.sin(theta1)
        sample[i, 2] = sample[i, 2] + r * np.sin(theta2)

    return sample

def generate_spiral(center, radius, theta_max, height, num_points):
    """
    Generates a spiral trajectory
    :param center: coordinates of the center of the containing cylinder
    :param radius: spiral radius
    :param theta_max: maximum angle of the spiral trajectory (0, +inf)
    :param height: height of the spiral along z
    :param num_points: number of points in the trajectory
    :return: a ndarray with the trajectory of points
    """
    theta_z = np.linspace(0, theta_max, num=num_points)

    spiral = np.zeros((num_points, 3))
    spiral[:, 0] = center[0] + radius * np.cos(np.radians(theta_z))
    spiral[:, 1] = center[1] + radius * np.sin(np.radians(theta_z))
    spiral[:, 2] = np.concatenate( (np.linspace(center[2] - height/2.0, center[2] + height/2.0, math.floor(num_points/2)),
                                    np.linspace(center[2] + height/2.0, center[2] - height/2.0, math.ceil(num_points/2))))

    return spiral

def generate_8_shape(center, radius, num_points):
    """
    Generates an eight-like  trajectory
    :param center: coordinates of shape center
    :param radius: shape radius
    :param num_points: number of points in the trajectory
    :return: a ndarray with the trajectory of points
    """
    t = np.linspace(0, 2*np.pi, num_points)
    z = center[2] * np.ones(num_points)
    return np.vstack((radius * np.sin(t) * np.cos(t) + center[0],
                    radius * np.sin(t) + center[1],
                    z
                    )).T

def sqdist(X1, X2):
    """ Given two matrices whose rows are points, computes the distances
    between all the points of the first matrix and all the points of the
    second matrix
    Arguments:
    X1: [N1 x d], earch row is a d-dimensional point
    X2: [N2 x d], each row is a d-dimensional point
    Returns:
    M: [N1 x N2], each element  is the distance between two points
    M_ij = || X1_i - X2_j ||"""

    if not isinstance(X1, np.ndarray):
        X1 = np.array(X1)
    if not isinstance(X2, np.ndarray):
        X2 = np.array(X2)
    if X1.ndim <= 1:
        sqx         = np.array(X1*X1, dtype=np.float32)
        rows_X1     = 1
    else:
        sqx = np.sum(np.multiply(X1, X1), 1)
        rows_X1     = sqx.shape[0]

    if X2.ndim <= 1:
        sqy         = np.array(X2*X2, dtype=np.float32)
        rows_X2     = 1
    else:
        sqy = np.sum(np.multiply(X2, X2), 1)
        rows_X2     = sqy.shape[0]
    X1_squares      = np.squeeze(np.outer(np.ones(rows_X1), sqy.T))
    X2_squares      = np.squeeze(np.outer(sqx, np.ones(rows_X2)))
    double_prod     = np.squeeze(2 * np.dot(X1,X2.T))

    return np.maximum(X1_squares + X2_squares - double_prod, np.zeros(X1_squares.shape))

def check_joint_limits_respected(lower_joint_limits, upper_joint_limits, joints_configuration_query):
    """
    Generates a circle trajectory
    :param lower_joint_limits: upper joint limits
    :param upper_joint_limits: lower joint limits
    :param joints_configuration_query: joints configuration to be checked
    :return: True if respected, False otherwise
    """

    # Check list sizes match
    assert len(lower_joint_limits) == len(upper_joint_limits) == len(joints_configuration_query)

    size = len(lower_joint_limits)

    is_ok = True
    for i in range(size):
        is_ok = lower_joint_limits[i] <= joints_configuration_query[i] <= upper_joint_limits[i]
        if not is_ok:
            break

    return is_ok

def compute_rmse(trajectory_1, trajectory_2):

    if trajectory_1.ndim == 2 and trajectory_2.ndim == 2:
        m1 = trajectory_1.shape[0]
        m2 = trajectory_2.shape[0]
        assert m1 == m2
    elif trajectory_1.ndim == 1 and trajectory_2.ndim == 1:
        m1 = 1
        assert trajectory_1.shape[0] == trajectory_2.shape[0]
    else:
        return np.nan

    mse = 0

    for i in range(m1):
        mse += np.linalg.norm(trajectory_1[i] - trajectory_2[i]) ** 2

    mse /= m1

    rmse = np.sqrt(mse)

    # TODO: vectorized form
    # error = np.linalg.norm(trajectory_1 - trajectory_2)
    # mse = np.sqrt(np.mean(np.sum(error ** 2))
    #               )

    return rmse

def predict_panda_trajectory_CRiSP(xte, invert_kin, forward, out, s, v, alg):

    predictions, data = invert_kin(xte, is_sequence=True)

    # Compare results on test set
    reconstructed = forward(predictions)
    error = np.full((xte.shape), np.inf)

    error[:,:3] = np.sqrt((reconstructed[:, :3] - xte[:, :3])**2)
    error[:, 3:] = np.sqrt(radial_squared_error(reconstructed[:, 3:], xte[:, 3:]))

    rmse_orientation = np.mean(np.sum(error[:, 3:], axis=1))
    var_orientation = np.std(np.sum(error[:, 3:], axis=1))

    rmse_position = np.mean(np.sum(error[:, :3], axis=1))
    var_position = np.std(np.sum(error[:, :3], axis=1))

    rmse = np.mean(np.sum(error, axis=1))
    var = np.std(np.sum(error, axis=1))

    out(f"\nAlgorithm: {alg}")
    results =   {'rmse_orientation': rmse_orientation,
                'var_orientation': var_orientation,
                'rmse_position': rmse_position,
                'var_position': var_position,
                'rmse': rmse,
                'var': var,
                'xte': xte,
                'alpha': data['alpha'],
                'Kx': data['Kx'],
                'trajectory_pos': reconstructed[:, :3],
                'trajectory_orn': reconstructed[:, 3:],
                'trajectory_joints_pred_CRiSP': predictions}

    out(f"s: {s}\t v: {v}")
    out(f"\t\tRMSE ori: {results['rmse_orientation']:7.6f} ± {results['var_orientation']:7.6f}")
    out(f"\t\tRMSE pos: {results['rmse_position']:7.6f} ± {results['var_position']:7.6f}\n"
             f"\t\tRMSE: {results['rmse']:7.6f} ± {results['var']:7.6f}")
    out(f"Norm of alphas = {np.linalg.norm(data['alpha'])}")

    return results

def predict_panda_trajectory_PB(xte, invert_kin, forward, out, s, v, alg):

    predictions = invert_kin(xte)

    # Compare results on test set
    reconstructed = forward(predictions)
    error = np.full((xte.shape), np.inf)

    error[:,:3] = np.sqrt((reconstructed[:, :3] - xte[:, :3])**2)
    error[:, 3:] = np.sqrt(radial_squared_error(reconstructed[:, 3:], xte[:, 3:]))

    rmse_orientation = np.mean(np.sum(error[:, 3:], axis=1))
    var_orientation = np.std(np.sum(error[:, 3:], axis=1))

    rmse_position = np.mean(np.sum(error[:, :3], axis=1))
    var_position = np.std(np.sum(error[:, :3], axis=1))

    rmse = np.mean(np.sum(error, axis=1))
    var = np.std(np.sum(error, axis=1))

    out(f"\nAlgorithm: PyBullet Inverse Kinematics")
    results = {'rmse_orientation': rmse_orientation, 'var_orientation': var_orientation,
                'rmse_position': rmse_position, 'var_position': var_position,
                'rmse': rmse, 'var': var, 'xte': xte, 'predictions': predictions,
               'trajectory_PyBullet_IK_reference_joints': predictions,
               'trajectory_pos_ikpb': reconstructed[:, :3],
               'trajectory_orn_ikpb': reconstructed[:, 3:],
               }
    out(f"\t\tRMSE ori: {results['rmse_orientation']:7.6f} ± {results['var_orientation']:7.6f}")
    out(f"\t\tRMSE pos: {results['rmse_position']:7.6f} ± {results['var_position']:7.6f}\n"
             f"\t\tRMSE: {results['rmse']:7.6f} ± {results['var']:7.6f}")

    return results


from numpy import exp, array, random, dot

class NeuralNetwork():
	def __init__(self):
		# Seed the random number generator, so it generates the same numbers
		# every time the program runs
		random.seed(1)

		# We model a single neuron, with 3 input connections and 1 output connection.
		# We assign random weights to a 3 x 1 matrix, with values in the range -1 to 1
		# and mean 0
		self.synaptic_weights = 2 * random.random((3, 1)) - 1

	# The sigmoid function, which describes an s shaped curve
	# We pass the weights sum of the inputs through this function
	# to normalize them between 0 and 1
	def __sigmoid(self, x):
		return 1 / (1 + exp(-x))

	# gradient of the sigmoid curve
	def __sigmoid_derivative(self, x):
		return x * (1 - x)

	def train(self, training_set_inputs, training_set_outputs, number_of_training_iterations):
		for i in range(number_of_training_iterations):
			# The neural network output (y-hat)
			# pass the training set through our neural net
			output = self.predict(training_set_inputs)

			# output error (y - y-hat)
			# calculate the error
			error = training_set_outputs - output

			# error term (lowercase delta) and Gradient descent step
			# multiply the error by the input ad again by the gradient of the sigmoid curve
			adjustment = dot(training_set_inputs.T, error * self.__sigmoid_derivative(output))

			# adjust the weights
			self.synaptic_weights += adjustment

	def predict(self, inputs):
		# pass inputs through our neural network (our single neuron)
		return self.__sigmoid(dot(inputs, self.synaptic_weights))

if __name__ == '__main__':

	# Initialize a single neuron neural network
	neural_network = NeuralNetwork()

	print 'Random starting synapsis weights:'
	print neural_network.synaptic_weights

	# The training set. We have 4 examples, each consisting of 3 input values
	# and 1 output value.
	training_set_inputs = array([[0, 0, 1], [1, 1, 1], [1, 0, 1], [0, 1, 1]])
	training_set_outputs = array([[0, 1, 1, 0]]).T

	# Train the neural network using a training set.
	# Do it 10,000 times and make small adjustment each time.
	neural_network.train(training_set_inputs, training_set_outputs, 10000)

	print "New synapsis weights after training: "
	print neural_network.synaptic_weights

	# Test the neural network with a new situation
	print "Considering new situation [1, 0, 0] -> ?: "
	print neural_network.predict(array([1, 0, 0]))


"""
surface

simply generate points on the surface of a sphere
can be used to test simple prolate/oblate models

04-Mar-2021: introduction

"""
import numpy as np

def gen_sphere_surface(npoints,cartesian=True):
    """generate evenly spaced points on the surface of a sphere

    inputs
    -------------
    npoints    : integer
        the maximum number of points to generate on the surface of the sphere
    cartesian  : boolean, default True
        if true, return (x,y,z). If false, return (phi,theta)

    note that npoints is the maximum, because we are enforcing
    equal spacing: not all npoints values return even spacing.

    returns
    -------------
    x,y,z      : arrays, npoints long
        cartesian location of points on the unit sphere
    phi,theta  : arrays, npoints long
        surface of sphere points in radians

    """
    npoint = 0
    points = np.zeros([npoints,3])
    sphpoints = np.zeros([npoints,2])

    a = 4*np.pi/npoints
    d = np.sqrt(a)
    Mtheta = np.floor(np.pi/d).astype('int')
    dtheta = np.pi/Mtheta
    dphi   = a/dtheta

    for m in range(0,Mtheta):

        theta = np.pi*(m+0.5)/Mtheta
        Mphi  = np.floor(2*np.pi*np.sin(theta)/dphi).astype('int')

        for n in range(0,Mphi):
            phi = 2*np.pi*n/Mphi
            points[npoint] = np.array([np.sin(theta)*np.cos(phi),
                                       np.sin(theta)*np.sin(phi),
                                       np.cos(theta)])
            sphpoints[npoint] = np.array([phi,theta])
            npoint += 1

    if cartesian:
        return points[:npoint,0],points[:npoint,1],points[:npoint,2]
    else:
        return sphpoints[:npoint,0],sphpoints[:npoint,1]


import numpy as np
import pprint

ITERATIONS = 200
LEARNING_RATE = 0.01
BIAS = 1

count = 0

# reads the dataset from CSV file and normalizes it
def getData(filename):
    data = np.loadtxt(filename, delimiter=',') # load csv file into numpy array
    # normalize data (ignore last column because that is desired output)
    normalized = data[:, :-1] / data[:, :-1].max(axis=0)
    # put normalized data back into array with desired output column
    data[:, :-1] = normalized
    return data

# output function of neuron which calculates the weighted sum of inputs
# the output is 1 if sum is greater than 0, 0 otherwise
def activate(input, weights):
    # add bias for neuron to determine its own threshold
    output = BIAS * weights[0]
    # list comprehension to perform element wise multiplication of the input
    # and weights lists
    output += sum([x * w for x, w in zip(input, weights[1:])])
    return 1 if output > 0 else 0

# implementation of a 2 neuron perceptron where weights1 is the set of input
# weights feeding into neuron 1 and weights2 is the set of input weights feeding
# into neuron 2
# the outputs are concatenated and treated like a binary string
def perceptron(input, weights1, weights2):
    y1 = activate(input, weights1)
    y2 = activate(input, weights2)
    return str(y1) + str(y2)

# helper function to update the weights of perceptron while training
def updateWeights(x, w, y, d):
    weights = []
    # update weight of BIAS input, resulting in perceptron determining its own
    # threshold
    weights.append(w[0] + ((d - y) * LEARNING_RATE * BIAS))
    # update weight, w, for each input, x
    for i in range(len(x)):
        weights.append(w[i+1] + ((d - y) * LEARNING_RATE * x[i]))
    return weights

def trainPerceptron(input, weights1, weights2):
    global count
    for i in range(ITERATIONS):
        for row in input:
            y = perceptron(row[:-1], weights1, weights2)
            # print('y is: {}, and d is: {}'.format(int(y,2), row[len(row)-1]))
            d = row[len(row)-1]
            test = format(int(d), '02b')
            if int(test[0]) - int(y[0]) != 0:
                weights1 = updateWeights(row[:-1], weights1, int(y[0]), int(test[0]))
            if int(test[1]) - int(y[1]) != 0:
                weights2 = updateWeights(row[:-1], weights2, int(y[1]), int(test[1]))
            if int(y, 2) - int(row[len(row)-1]) == 0:
                count += 1
            # print(y)
        print('This many were right: {}'.format(count))
        count = 0
    print(weights1)
    print(weights2)
    return (weights1, weights2)

def testPerceptron(input, weights1, weights2):
    global count
    count = 0
    for row in input:
        y = perceptron(row[:-1], weights1, weights2)
        d = row[len(row)-1]
        # print(y)
        if int(y, 2) - int(d) == 0:
            count +=1
    print('This many were right: {}'.format(count))

def main():
    weights1 = [-0.1, 1, 0.1, 1, 0.1, -1, 0.1, -1]
    weights2 = [-1, 0.1, 1, 0.1, 1, 0.1, 1, 0.1]
    # first weight is for bias
    # weights1 = [-0.3600000000000002, 1.0124787535410458, 0.008660869565218606, 0.3704475661548351, -0.14466367041199163, -1.1815497148523761, 0.125947634237115, 0.47409770992366457]
    # weights2 = [-0.3399999999999994, -1.1172521246458798, 0.544226086956539, 0.7400718719372663, 0.7303610486891207, -0.307255145053313, -0.1705348219032502, -0.35072519083968534]

    trainingData = getData('trainSeeds.csv')
    np.random.shuffle(trainingData)

    # train perceptron
    weights1, weights2 = trainPerceptron(trainingData, weights1, weights2)

    testData = getData('testSeeds.csv')
    np.random.shuffle(testData)

    testPerceptron(testData, weights1, weights2)

if __name__ == '__main__':
    main()


import numpy as np
import matplotlib.pyplot as plt

def deltau(u):
    # central difference
    return np.r_[-3*u[0]+4*u[1]-u[2],  u[2:]-u[:-2],  3*u[-1]-4*u[-2]+u[-3]]

def laplacianCyl(r, u):
    # (1/r) (r u_r)_r
    dr = r[1] - r[0]
    dudr = deltau(u)/(2*dr)
    return deltau(r*dudr)/(2*dr)/r

def laplacianSph(r, u):
    # (1/r*r) (r*r u_r)_r
    dr = r[1] - r[0]
    dudr = deltau(u)/(2*dr)
    return deltau(r*r*dudr)/(2*dr)/(r*r)

def laplacianCar(y, u):
    # u_yy
    dy = y[1] - y[0]
    return np.r_[2*u[0]-5*u[1]+4*u[2]-u[3], u[2:]+u[:-2]-2*u[1:-1], 2*u[-1]-5*u[-2]+4*u[-3]-u[-4]]/(dy*dy)

def test_sine():
    x = np.linspace(0, 2*np.pi)
    y = np.sin(x)
    plt.plot(x, laplacianCar(x,y), 'r--o', x, -np.sin(x), 'k-')
    plt.show()

if __name__ == "__main__":
    test_sine()


from numpy import sqrt, mean, square, array, count_nonzero

class Metric():

    greater_is_better = None

    @staticmethod
    def evaluate(prediction, target):
        pass

class RootMeanSquaredError(Metric):

    greater_is_better = False

    @staticmethod
    def evaluate(prediction, target):
        return sqrt(mean(square(prediction - target)))

class Accuracy(Metric):

    greater_is_better = True

    @staticmethod
    def evaluate(prediction, target):
        prediction_label = prediction > 0.5
        return count_nonzero(prediction_label == target) / prediction.shape[0]

def is_better(value_1, value_2, metric):
    if metric.greater_is_better:
        return value_1 > value_2
    else:
        return value_1 < value_2


import numpy as np

def l1(alpha, w,grad=False):
    if grad:
        return alpha * np.sign(w)
    else:
        return alpha * np.sum(np.abs(w))

def l2(alpha, w, grad=False):
    if grad:
        return alpha * w
    else:
        return alpha * np.sum(w * w)

def l1_l2(alpha, w, l1_ratio = 0.5, grad=False):
    if grad:
        return alpha * ((l1_ratio * np.sign(w)) + ((1 - l1_ratio) * w))
    else:
        return alpha * ((l1_ratio * np.sum(np.abs(w))) + ((1 - l1_ratio) * np.sum(w * w)))


import numpy as np

class LinearRegression:
    DEFAULT_ALPHA = 0.0005
    DEFAULT_EPOCHS_COUNT = 1000

    def __init__(self, x: np.ndarray, y: np.ndarray):
        self.y = y
        self.x = self._construct_x(x)
        self.theta = np.ones(2).reshape(2, 1)

    def precompute(self, alpha=DEFAULT_ALPHA, epochs_count=DEFAULT_EPOCHS_COUNT) -> np.ndarray:
        """
        Prepare model.

        Use Gradient Dissent to prepare model for future use.

        :param alpha: Learning rate for the model.
        :param epochs_count: Iterations count for Gradient Dissent.
        :return: Theta data (np.ndarray[b, multiplier]).
        """
        for _ in range(int(np.sqrt(epochs_count))):
            self._gd(alpha, epochs_count)
        return self.theta

    def _gd(self, alpha: float, epochs_count: int) -> np.ndarray:
        hx = np.matmul(self.x, self.theta)
        cost_1 = self.compute_cost(self.theta)
        for _ in range(epochs_count):
            temp = (alpha / self.y.size) * np.matmul(self.x.T, (hx - self.y))
            cost_2 = self.compute_cost(self.theta - temp)

            if cost_1 > cost_2:
                cost_1 = cost_2
                self.theta -= temp

        return self.theta

    def compute_cost(self, theta=None) -> float:
        """
        Compute sum of squared error.

        :param theta: Theta data (np.ndarray[b, multiplier]).
        :return: Calculated sum of squared error.
        """
        if theta is None:
            theta = self.theta
        hx = np.matmul(self.x, theta)
        return np.sum(np.power(np.subtract(hx, self.y), 2)) / (2 * self.y.size)

    def predict(self, one_x: float) -> float:
        b, m = self.theta[0][0], self.theta[1][0]
        return one_x * m + b

    @staticmethod
    def _construct_x(x: np.ndarray) -> np.ndarray:
        return np.hstack((np.ones(x.size).reshape(x.size, 1), x))

    def r2_score(self, x: np.ndarray, y: np.ndarray) -> float:
        """
        Calculate the r2 score of the model.

        :param x: Input dataset.
        :param y: Target dataset.
        :return Calculated r2 score of the model.
        """
        predicted = self._construct_x(x) @ self.theta
        return 1 - np.sum((y - predicted) ** 2) / np.sum((y - y.mean()) ** 2)


import numpy as np
import matplotlib.pyplot as plt

N = 50

# generate the data
X = np.linspace(0,10,N)
Y = 0.5*X + np.random.randn(N)

# make outliers
Y[-1] += 30
Y[-2] += 30

# plot the data
plt.scatter(X, Y)
plt.show()

# add bias term
X = np.vstack([np.ones(N), X]).T

# plot the maximum likelihood solution
w_ml = np.linalg.solve(X.T.dot(X), X.T.dot(Y))
Yhat_ml = X.dot(w_ml)
plt.scatter(X[:,1], Y)
plt.plot(X[:,1], Yhat_ml)
plt.show()

# plot the regularized solution
# probably don't need an L2 regularization this high in many problems
# everything in this example is exaggerated for visualization purposes
l2 = 1000.0
w_map = np.linalg.solve(l2*np.eye(2) + X.T.dot(X), X.T.dot(Y))
Yhat_map = X.dot(w_map)
plt.scatter(X[:,1], Y)
plt.plot(X[:,1], Yhat_ml, label='maximum likelihood')
plt.plot(X[:,1], Yhat_map, label='map')
plt.legend()
plt.show()


from __future__ import division
import numpy as np

'''
This file contains implementation of various activation functions.
'''

#Random seed for consistency in results.
np.random.seed(32)

def sigmoid(tensor):
    '''
    Sigmoid transfer.
    :param tensor: numpy array
    :return: numpy array of same shape, where each input element has been modified.
    '''
    return 1/(1+np.exp(-tensor))

def tanh(tensor):
    '''
    Hyperbolic tangent.
    :param tensor: numpy array.
    :return: numpy array of same shape, where each input element has been modified.
    '''
    return np.tanh(tensor)

def ReLU(tensor):
    '''
    Rectified Linear Unit
    :param tensor:numpy array
    :return: numpy array of same shape, where each input element has been rectified with noise.
    '''
    return np.maximum(0,tensor)

def Noisy_ReLU(tensor):
    '''
    Nosiy Rectified Linear Unit. The noise is chosen from a
    gaussian distribution of zero mean and unit variance.
    :param tensor: numpy array
    :return: numpy array of same shape, where each input element has been rectified.
    '''
    return np.maximum(0,tensor+np.random.normal(0,1))

def Leaky_ReLU(tensor):
    '''
    Leaky Rectified Linear Unit.
    :param tensor: numpy array
    :return: numpy array of same shape.
    '''
    tensor[tensor<0] *= 0.01
    return tensor

def softmax(tensor):
    '''
    Softmax function(normalized exponential): changes array of arbitrary real
    values into array of real values in the range (0,1) that add upto 1.
    Softmax usually fails for large numbers so we will shift the numbers and then calculate.
    :param tensor: 1D numpy array.
    :return: softmax transferred numpy array of same dimension.
    '''
    tensor = tensor -np.max(tensor, axis=1,keepdims=True)
    exp = np.exp(tensor)
    return exp/np.sum(exp, axis=1,keepdims=True)


import numpy as np

def rand_init_weight(Lin, Lout):
    """One effective strategy for choosing init is to base it on the number of units in the
       network. A good choice of epsilon is

       epsilon =√6/√(Lin+Lout)

       here Lin = sl and Lout = sl+1 are the number of units in the layers adjacent to Θ(l)
    """
    W = np.zeros((Lout, Lin+1))
    epsilon = np.sqrt(6)/np.sqrt(Lin+Lout)

    W = np.random.uniform(size=(Lout, Lin+1)) * 2 * epsilon - epsilon

    return W


import numpy as np
import matplotlib.pyplot as plt

#------------------------------Question 1--------------------------
def rp(x,p):
    t=1
    i=0
    if x==0 :
        return 0

    if x>1 or x<-1 : # si mon nombre n'est pas de la forme 0,....
        # on calcul t tel que x*t soit de la forme [+-][0-9],....
        while x*t>=10 or x*t<= -10 :
            t/=10
            i+=1
        res=round(x*t,p-1)*10**i

    else : # si mon nombre est de la forme 0,.....
        # on calcul t tel que x*t soit de la forme [+-][0-9],....
        while -1<=x*t<=1  :
            t*=10
            i+=1
        res = round(x,p-1+i)

    return res

def test_rp():
    print(rp(3.141592658,4))
    print(rp(3.141592658,6))
    print(rp(10507.1823,4))
    print(rp(10507.1823,6))
    print(rp(0.0001857563,4))
    print(rp(0.0001857563,6))

#test_rp()

#------------------------------Question 2--------------------------
def rp_add(x,y,p):
    return rp(rp(x,p)+rp(y,p),p)
def rp_multi(x,y,p):
    return rp(rp(x,p)*rp(y,p),p)

#------------------------------Question 3--------------------------
def erreur_relative_add (x,y,p):
    return abs((x+y)-rp_add(x,y,p))/abs(x+y)
def erreur_relative_multi (x,y,p):
    if (x==0 or y==0):
        return 0 ;
    return abs((x*y)-rp_multi(x,y,p))/abs(x*y)

#------------------------------Question 4--------------------------
def tracer(x,y)  :
    a=-y
    b=y
    y=np.linspace(a,b,201)
    z=np.linspace(0,0,201)
    t=np.linspace(0,0,201)
    for i in range (0,201):
        z[i]=erreur_relative_add(x,y[i],3)
        t[i]=erreur_relative_multi(x,y[i],3)
    plt.plot(y,z,label="Erreur relative de l'addition")
    plt.plot(y,t,label="Erreur relative de la multiplication")
    plt.title("Erreurs relatives sur l'addition et la multiplication")
    plt.legend()
    plt.xlabel("y")
    plt.ylabel("Erreur relative")
    plt.show()

#tracer(1000000,1)        Tests pour différentes valeurs de x
#tracer(100000,40)
tracer(0.000119,1)

#------------------------------Question 5--------------------------
def log_2(p):
    s=0
    signe=1
    t=10**p
    erreur=0
    for i in range (1,t):
        s+=signe/i
        signe*=-1
    return rp(s,p)

def rp_log_2(p):
    s=0
    signe=1
    t=10**p
    for i in range (1,t):
        s=rp_add(s,signe/i,p)
        signe*=-1
    return rp(s,p)
def test_log ():
    a2=rp(np.log(2),9)
    a1=rp(np.log(2),5)
    b1=rp_log_2(5)
    b2=log_2(9)
    print("l'erreur relative du calcul de log 2 en utilisant l'addition machine  sur 9 decimal est ", a2,"-",b2,"=",abs(a2-b2))
    print("l'erreur relative du calcul de log 2 en utilisant l'addition definie sur  5 decimal est ", a1,"-",b1,"=",abs(a1-b1))
#test_log()
#l'erreur relative du calcul de log 2 en utilisant l'addition machine  sur 9 decimal est  0.693147181 - 0.693147181 = 0.0
#l'erreur relative du calcul de log 2 en utilisant l'addition definie sur  5 decimal est  0.69315 - 0.69321 = 5.99999999999e-05


import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
import sys
import os

(x_train,y_train) , (x_test,y_test) = load_mnist(True,True,True)

tf.set_random_seed(777)  # reproducibility
np.random.seed(7)

batchSize = 100
trainEpoch = 3000

lr = 0.5
iSize = 784
h1Size = 50
h2Size = 50
oSize = 10

X = tf.placeholder( tf.float32 , [None,iSize])
Y = tf.placeholder( tf.float32  , [None , oSize])

#Layer
#W1 = tf.Variable( tf.random_normal( [iSize , h1Size] ) , name="W1" )
#b1 = tf.Variable( tf.zeros( [h1Size] ))
#
#W2 = tf.Variable( tf.random_normal( [h1Size , h2Size] ) , name="W2" )
#b2 = tf.Variable( tf.zeros( [h2Size] ))
#
#W3 = tf.Variable( tf.random_normal( [h2Size , oSize] ) , name="W3" )
#b3 = tf.Variable( tf.zeros( [oSize] ))

W1 = tf.Variable(  shape = [iSize , h1Size]  , name="W1", initializer = tf.contrib.layers.xavier_initializer() )
b1 = tf.Variable( tf.zeros( [h1Size] ))

W2 = tf.Variable( shape = [h1Size , h2Size]  , name="W2" , initializer = tf.contrib.layers.xavier_initializer())
b2 = tf.Variable( tf.zeros( [h2Size] ))

W3 = tf.Variable(  shape = [h2Size , oSize]  , name="W3" , initializer = tf.contrib.layers.xavier_initializer() )
b3 = tf.Variable( tf.zeros( [oSize] ))

#Output

L1 = tf.nn.relu( tf.matmul( X , W1) + b1 )
L2 = tf.nn.relu( tf.matmul( L1 , W2 ) + b2)

Output = tf.nn.softmax( tf.matmul( L2 , W3 ) + b3)

Loss = tf.reduce_mean( - tf.reduce_sum( Y * tf.log( Output ) , reduction_indices = [1] ) )

optimizer = tf.train.AdagradOptimizer( lr ).minimize( Loss )
#optimizer = tf.train.GradientDescentOptimizer( lr ).minimize( Loss )

#init

sess =tf.Session()
sess.run( tf.global_variables_initializer() )

LossList = []
LossTest = []

for i in range(0,trainEpoch):
	batchMask = np.random.choice( x_train.shape[0] , batchSize)
	xBatch = x_train[batchMask]
	yBatch = y_train[batchMask]

	lossTrain , _ = sess.run([Loss , optimizer] , feed_dict = { X  :xBatch , Y : yBatch })
	lossTest = sess.run([Loss] , feed_dict = { X  :x_test , Y : y_test })

	LossList.append(loss)
	LossTest.append(lossTest)

#plot

plt.title( "Loss Graph" )
plt.xlabel( "Epoch" )
plt.ylabel( "Cross Entropy Loss" )
plt.plot(LossList , 'r--' )
plt.plot(LossTest , 'b' )
plt.show()


#!/usr/bin/env python3

import numpy as np

def er_random(N, p):
    '''
    Construct an unweighted bi-directional ER random network without self-loop

    Arguments:
    1. N:    Total number of nodes in the network
    2. p:    Connection probability

    Returns:
    1. A:    Adjacency matrix
    '''
    assert type(N) == int and N > 0, "N must be a positive integer"
    assert (type(p) == int or type(p) == float), "p must be a real number"
    assert p >= 0 and p <= 1, "p must be within 0 and 1 (inclusive)"

    if p == 0:
        print("[WARN] p = 0, the network has no links")
        A = np.zeros((N, N))
        return A

    elif p == 1:
        print("[WARN] p = 1, the network is fully connected")
        A = np.ones((N, N))
        return A

    else:
        # Generate a random matrix with size N x N
        # Each element takes value between 0 and 1
        A = np.random.rand(N, N)

        # Set the connectivity based on input probability threshold p
        A = A < p
        A = A.astype(int)

        # Extract only the upper triangle elements
        # And set other (lower triangle + diagonal) to zero
        A = np.triu(A, 1)

        # Symmetrize the matrix
        A = A + A.T

        return A


import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import newton

R = 8.314e-5  # universal gas constant, m3-bar/K-mol
class Molecule:
    """
    Store molecule info here
    """
    def __init__(self, name, Tc, Pc, omega):
        """
        Pass parameters desribing molecules
        """
        #! name
        self.name = name
        #! Critical temperature (K)
        self.Tc = Tc
        #! Critical pressure (bar)
        self.Pc = Pc
        #! Accentric factor
        self.omega = omega

    def print_params(self):
        """
        Print molecule parameters.
        """
        print("""Molecule: %s.
        \tCritical Temperature = %.1f K
        \tCritical Pressure = %.1f bar.
        \tAccentric factor = %f""" % (self.name, self.Tc, self.Pc, self.omega))

def preos(molecule, T, P, plotcubic=True, printresults=True):
    """
    Peng-Robinson equation of state (PREOS)
    http://en.wikipedia.org/wiki/Equation_of_state#Peng.E2.80.93Robinson_equation_of_state
    :param molecule: Molecule molecule of interest
    :param T: float temperature in Kelvin
    :param P: float pressure in bar
    :param plotcubic: bool plot cubic polynomial in compressibility factor
    :param printresults: bool print off properties

    Returns a Dict() of molecule properties at this T and P.
    """
    # build params in PREOS
    Tr = T / molecule.Tc  # reduced temperature
    a = 0.457235 * R**2 * molecule.Tc**2 / molecule.Pc
    b = 0.0777961 * R * molecule.Tc / molecule.Pc
    kappa = 0.37464 + 1.54226 * molecule.omega - 0.26992 * molecule.omega**2
    alpha = (1 + kappa * (1 - np.sqrt(Tr)))**2

    A = a * alpha * P / R**2 / T**2
    B = b * P / R / T

    # build cubic polynomial
    def g(z):
        """
        Cubic polynomial in z from EOS. This should be zero.
        :param z: float compressibility factor
        """
        return z**3 - (1 - B) * z**2 + (A - 2*B - 3*B**2) * z - (
                A * B - B**2 - B**3)

    # Solve cubic polynomial for the compressibility factor
    z = newton(g, 1.0)  # compressibility factor
    rho = P / (R * T * z)  # density

    # fugacity coefficient comes from an integration
    fugacity_coeff = np.exp(z - 1 - np.log(z - B) - A / np.sqrt(8) / B * np.log(
                (z + (1 + np.sqrt(2)) * B) / (z + (1 - np.sqrt(2)) * B)))

    if printresults:
        print("""PREOS calculation at
        \t T = %.2f K
        \t P = %.2f bar""" % (T, P))
        print("\tCompressibility factor : ", z)
        print("\tFugacity coefficient: ", fugacity_coeff)
        print("\tFugacity at pressure %.3f bar = %.3f bar" % (
                P, fugacity_coeff * P))
        print("\tDensity: %f mol/m3" % rho)
        print("\tMolar volume: %f L/mol" % (1.0 / rho * 1000))
        print("\tDensity: %f v STP/v" % (rho * 22.4 / 1000))
        print("\tDensity of ideal gas at same conditions: %f v STP/v" % (
                rho * 22.4/ 1000 * z))

    if plotcubic:
        # Plot the cubic equation to visualize the roots
        zz = np.linspace(0, 1.5)  # array for plotting

        plt.figure()
        plt.plot(zz, g(zz), color='k')
        plt.xlabel('Compressibility, $z$')
        plt.ylabel('Cubic $g(z)$')
        plt.axvline(x=z)
        plt.axhline(y=0)
        plt.title('Root found @ z = %.2f' % z)
        plt.show()
    return {"density(mol/m3)": rho, "fugacity_coefficient": fugacity_coeff,
            "compressibility_factor": z, "fugacity(bar)": fugacity_coeff * P,
            "molar_volume(L/mol)": 1.0 / rho * 1000.0}

def preos_reverse(molecule, T, f, plotcubic=False, printresults=True):
    """
    Reverse Peng-Robinson equation of state (PREOS) to obtain pressure for a particular fugacity
    :param molecule: Molecule molecule of interest
    :param T: float temperature in Kelvin
    :param f: float fugacity in bar
    :param plotcubic: bool plot cubic polynomial in compressibility factor
    :param printresults: bool print off properties

    Returns a Dict() of molecule properties at this T and f.
    """
    # build function to minimize: difference between desired fugacity and that obtained from preos
    def g(P):
        """
        :param P: pressure
        """
        return (f - preos(molecule, T, P, plotcubic=False, printresults=False)["fugacity(bar)"])

    # Solve preos for the pressure
    P = newton(g, f)  # pressure

    # Obtain remaining parameters
    pars = preos(molecule, T, P, plotcubic=plotcubic, printresults=printresults)
    rho = pars["density(mol/m3)"]
    fugacity_coeff = pars["fugacity_coefficient"]
    z = pars["compressibility_factor"]

    return {"density(mol/m3)": rho, "fugacity_coefficient": fugacity_coeff,
            "compressibility_factor": z, "pressure(bar)": P,
            "molar_volume(L/mol)": 1.0 / rho * 1000.0}

# TODO: Implement mixture in object-oriented way as well
def preos_mixture(molecule_a, molecule_b, delta, T, P_total, x, plotcubic=True, printresults=True):
    """
    Peng-Robinson equation of state (PREOS) for a binary mixture
    http://en.wikipedia.org/wiki/Equation_of_state#Peng.E2.80.93Robinson_equation_of_state
    :param molecule_a: Molecule molecule 1 of interest
    :param molecule_b: Molecule molecule 2 of interest
    :param delta: binary interaction parameter between molecules a and b
    :param T: float temperature in Kelvin
    :param P_total: float total pressure in bar
    :param x: array mole fractions
    :param plotcubic: bool plot cubic polynomial in compressibility factor
    :param printresults: bool print off properties
    """
    # build arrays of properties
    Tc = np.array([molecule_a.Tc, molecule_b.Tc])
    Pc = np.array([molecule_a.Pc, molecule_b.Pc])
    omega = np.array([molecule_a.omega, molecule_b.omega])

    # build params in PREOS
    Tr = T / Tc  # reduced temperature
    a0 = 0.457235 * R**2 * Tc**2 / Pc
    b = 0.0777961 * R * Tc / Pc
    kappa = 0.37464 + 1.54226 * omega - 0.26992 * omega**2
    a = a0 * (1 + kappa * (1 - np.sqrt(Tr)))**2

    # apply mixing rules
    aij = (1.0 - delta) * np.sqrt(a[0] * a[1])
    a_mix = a[0] * x[0]**2 + a[1] * x[1]**2 + 2.0 * x[0] * x[1] * aij
    b_mix = x[0] * b[0] + x[1] * b[1]
    A = a_mix * P_total / R**2 / T**2
    B = b_mix * P_total / R / T

    # build cubic polynomial
    def g(z):
        """
        Cubic polynomial in z from EOS. This should be zero.
        :param z: float compressibility factor
        """
        return z**3 - (1 - B) * z**2 + (A - 2*B - 3*B**2) * z - (
                A * B - B**2 - B**3)

    # Solve cubic polynomial for the compressibility factor
    z = newton(g, 1.0)  # compressibility factor
    rho = P_total / (R * T * z)  # density

    Lnfug_0 = -np.log(z - B) + (z - 1.0) * b[0] / b_mix - A / np.sqrt(8) / B * (2.0 / a_mix * (x[0] * a[0] + x[1] * aij) - b[0] / b_mix) *\
        np.log((z + (1.0 + np.sqrt(2)) * B) / (z + (1.0 - np.sqrt(2)) * B))
    Lnfug_1 = -np.log(z - B) + (z - 1.0) * b[1] / b_mix - A / np.sqrt(8) / B * (2.0 / a_mix * (x[1] * a[1] + x[0] * aij) - b[1] / b_mix) *\
        np.log((z + (1.0 + np.sqrt(2)) * B) / (z + (1.0 - np.sqrt(2)) * B))

    # fugacity coefficient comes from an integration
    fugacity_coefs = np.exp(np.array([Lnfug_0, Lnfug_1]))

    if printresults:
        print("""PREOS calculation at
        \t T = %.2f K
        \t P, total = %.2f bar""" % (T, P_total))
        print("\tDensity: %f mol/m3" % rho)
        print("\tCompressibility factor : %f" % z)
        print("Component 0, %s:" % molecule_a.name)
        print("\tFugacity coefficient: %f" % fugacity_coefs[0])
        print("\tFugacity: %f bar" % (fugacity_coefs[0] * x[0] * P_total))
        print("Component 1, %s:" % molecule_b.name)
        print("\tFugacity coefficient: %f" % fugacity_coefs[1])
        print("\tFugacity: %f bar" % (fugacity_coefs[1] * x[1] * P_total))

    if plotcubic:
        # Plot the cubic equation to visualize the roots
        zz = np.linspace(0, 1.5)  # array for plotting

        plt.figure()
        plt.plot(zz, g(zz), color='k')
        plt.xlabel('Compressibility, $z$')
        plt.ylabel('Cubic $g(z)$')
        plt.axvline(x=z)
        plt.axhline(y=0)
        plt.title('Root found @ z = %.2f' % z)
        plt.show()
    return {"density(mol/m3)": rho, "fugacity_coefficients": fugacity_coefs,
            "compressibility_factor": z}


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Mathematical utility functions
"""

import numpy as np
from numba import jit

@jit(nopython=True, cache=True)
def xyz2sph(v):
    """
    Convert a unit vector from cartesian coordinates to spherical coordinates
    :param v: unit vector
    :return: [theta, phi] polar coordinates
    """

    return np.array([np.arccos(v[2]), np.arctan2(v[1], v[0])])

@jit(nopython=True, cache=True)
def sph2xyz(theta, phi):
    """
    Convert spherical coordinates to unit vector
    :param theta: theta angle
    :param phi: phi angle
    :return: (x, y, z) coordinates
    """
    x = np.sin(theta) * np.cos(phi)
    y = np.sin(theta) * np.sin(phi)
    z = np.cos(theta)
    return np.array([x, y, z])

@jit(nopython=True, cache=True)
def sph_dot(theta1, theta2, delta_phi):
    """
    Compute the dot product of two unit vectors in spherical coordinates
    """
    return np.sin(theta1) * np.cos(delta_phi) * np.sin(theta2) + np.cos(theta1) * np.cos(theta2)

@jit(nopython=True, cache=True)
def sph_urand():
    """
    Generate random unit vector in spherical coordinates
    :return: (theta, phi) the two angles
    """

    phi = np.random.uniform(0, 2 * np.pi)
    u = np.random.uniform(0, 1)
    theta = np.arccos(2 * u - 1)

    return theta, phi


# salimt
# Import libraries
# Import libraries
import numpy as np
from scipy import optimize

# First we define the functions, YOU SHOULD IMPLEMENT THESE
def f (x, y) :
  return - np.exp(x - y**2 + x*y)

def g (x, y) :
  return np.cosh(y) + x - 2

def dfdx (x, y) :
  return (1 + y) * f (x, y)

def dfdy (x, y) :
  return (- 2*y + x) * f (x, y)

def dgdx (x, y) :
  return 1

def dgdy (x, y) :
  return np.sinh(y)

# Use the definition of DL from previously.
def DL (xyλ) :
    [x, y, λ] = xyλ
    return np.array([
            dfdx(x, y) - λ * dgdx(x, y),
            dfdy(x, y) - λ * dgdy(x, y),
            - g(x, y)
        ])

# To score on this question, the code above should set
# the variables x, y, λ, to the values which solve the
# Langrange multiplier problem.

# I.e. use the optimize.root method, as you did previously.

x, y, λ = (1,0,1)
x, y, λ = optimize.root(DL, [x, y, λ]).x
print("x = %g" % x)
print("y = %g" % y)
print("λ = %g" % λ)
print("f(x, y) = %g" % f(x, y))

Imperial College London - Mathematics for Machine Learning Specialization/Imperial College London - Mathematics for Machine Learning Multivariate Calculus/lagrange-multipliers.py


import numpy as np
from scipy import sparse

def comm_classes(P):
    '''
    Parameters:
        P - scipy.sparse.csr_matrix
            Markov chain transition matrix, rows sum to 1

    Outputs:
        classes - list
            List of lists describing the communication classes of the Markov chain
        types - list
            List of communication class types, Transient or Absorbing, corresponding to classes output
    '''
    num_classes,class_map = sparse.csgraph.connected_components(P,directed = True,connection = 'strong')

    CC = []
    for i in range(num_classes):
        CC += [list(np.where(class_map == i)[0])]

    Ts = []
    transient_classes = np.array([])
    for i in range(num_classes):
        if sum([P[CC[i][0],j] for j in CC[i]]) < 1:
            Ts += ['Transient']
            transient_classes = np.append(transient_classes,i)
        else:
            Ts += ['Absorbing']
    transient_classes = [int(i) for i in transient_classes]
    order = list(transient_classes) + [int(i) for i in range(num_classes) if not i in transient_classes]
    classes = []
    types = []
    for i in order:
        classes += [CC[i]]
        types += [Ts[i]]
    return classes, types

def decompose(P,classes,types):
    '''
    Parameters:
        P - scipy.sparse.csr_matrix
            Markov chain transition matrix, rows sum to 1
        classes - list
            List of lists describing the communication classes of the Markov chain
        types - list
            List of communication class types, Transient or Absorbing, corresponding to classes output

    Outputs:
        diagonal - list
            list of scipy.sparse.csr_matrix objects along the diagonal for sub-markov chains
        upper_triangle - list
            list of scipy.sparse.csr_matrix objects upper triangle matrices indicating transient class escape probabilities
    '''
    num_classes = len(classes)
    state_order = []
    for i in range(num_classes):
        state_order += classes[i]

    diagonal = []
    upper_triangle = []
    for i in range(num_classes):
        diagonal += [P[classes[i],:][:,classes[i]]]
        if types[i] == 'Transient':
            state_order = [j for j in state_order if not j in classes[i]]
            upper_triangle += [P[classes[i],:][:,state_order]]
    diagonal = [sparse.csr_matrix(d) for d in diagonal]
    upper_triangle = [sparse.csr_matrix(d) for d in upper_triangle]
    return diagonal,upper_triangle

def construct_canonical_matrix(diagonal,upper_triangle):
    '''
    Inputs:
        diagonal - list
            list of scipy.sparse.csr_matrix objects along the diagonal for sub-markov chains
        upper_triangle - list
            list of scipy.sparse.csr_matrix objects upper triangle matrices indicating transient class escape probabilities

    Outputs:
        A - scipy.sparse.csr_matrix
            Markov chain transition matrix in canonocal format
        Q - scipy.sparse.csr_matrix
            Transient portionof the Markov chain
        R - scipy.sparse.csr_matrix
            Escape probability matrix from the transient portion to absorbing
        I - scipy.sparse.csr_matrix
            Absorbing class submatrix, itself a transition matrix

        A = (Q | R)
            (0 | I)
    '''
    N = sum([d.shape[0] for d in diagonal])
    A = np.zeros((N,N))
    Tstates = 0
    current_loc = 0
    for i in range(len(diagonal)):
        if i < len(upper_triangle):
            m,n = upper_triangle[i].shape
            A[current_loc:current_loc+m,current_loc+m:current_loc+m+n] = upper_triangle[i].todense()
            Tstates += m
        else:
            m = diagonal[i].shape[0]
        A[current_loc:current_loc+m,current_loc:current_loc+m] = diagonal[i].todense()
        current_loc += m
    Q = sparse.csr_matrix(A[:Tstates,:Tstates])
    R = sparse.csr_matrix(A[:Tstates,Tstates:])
    I = sparse.csr_matrix(A[Tstates:,Tstates:])
    A = sparse.csr_matrix(A)
    return A,Q,R,I


"""
Generation an autocorrelation matp
# https://stackoverflow.com/questions/30143417/computing-the-correlation-coefficient-between-two-multi-dimensional-arrays
"""
import numpy as np

def generate_correlation_map(data):
    """Correlate each n with each m.

    Parameters
    ----------
    x : np.array
      Shape N X T.

    y : np.array
      Shape M X T.

    Returns
    -------
    np.array
      N X M array in which each element is a correlation coefficient.

    """
    dt = np.mean(data._data, axis=1) #avg over channels
    x = np.transpose(dt)
    y = x.copy()

    mu_x = x.mean(1)
    mu_y = y.mean(1)
    n = x.shape[1]
    if n != y.shape[1]:
        raise ValueError('x and y must ' +
                         'have the same number of timepoints.')
    s_x = x.std(1, ddof=n - 1)
    s_y = y.std(1, ddof=n - 1)
    cov = np.dot(x,
                 y.T) - n * np.dot(mu_x[:, np.newaxis],
                                  mu_y[np.newaxis, :])
    return cov / np.dot(s_x[:, np.newaxis], s_y[np.newaxis, :])


# Analytic Hierarchy Process

import numpy as np

# class myAHP
class myAHP:
    # __init__(self)
    def __init__(self):
        # print("__init__(self).start...")

        self.RI_dict = {
             1: 0,       2: 0,        3: 0.58,    4: 0.90,    5:  1.12,   6: 1.24,    7: 1.32,
             8: 1.41,    9: 1.45,    10: 1.51,   11: 1.54,   12: 1.56,   13: 1.57,   14: 1.59,
            15: 1.59,   16: 1.60,    17: 1.61,   18: 1.62,   19: 1.63,   20: 1.64
        }
        self.comparison_matrix = np.array([
            [0.50, 0.77, 0.48, 0.68, 0.47, 0.38],
            [0.23, 0.50, 0.28, 0.45, 0.32, 0.23],
            [0.52, 0.72, 0.50, 0.75, 0.48, 0.40],
            [0.32, 0.55, 0.25, 0.50, 0.23, 0.20],
            [0.53, 0.68, 0.52, 0.77, 0.50, 0.48],
            [0.62, 0.77, 0.60, 0.80, 0.52, 0.50]
        ])
    # __init__(self)

    # get_w(array)
    def get_w(self, array):
        print("get_w(array).start...")

        row = array.shape[0]

        a_axis_0_sum = array.sum(axis=0)
        # print(a_axis_0_sum)

        b = array / a_axis_0_sum  # new matrix b
        # print(b)

        b_axis_0_sum = b.sum(axis=0)
        b_axis_1_sum = b.sum(axis=1)  #
        print("b_axis_1_sum")
        print(b_axis_1_sum)

        w = b_axis_1_sum / row  #

        nw = w * row

        AW = (w * array).sum(axis=1)
        print("AW:")
        print(AW)

        max_max = sum(AW / (row * w))
        print("max_max:")
        print(max_max)

        # calculating
        print("calculating")
        CI = (max_max - row) / (row - 1)
        print("CI:")
        print(CI)
        print("row:")
        print(row)
        print("RI_dictt[row]")
        print(self.RI_dict[row])
        print("/*------------------------*/")
        CR = CI / self.RI_dict[row]
        print("over!")

        if CR < 0.1:
            print("CR:")
            print(CR)
            # print(round(CR, 3))
            print('success!!')
            return w
        else:
            print(round(CR, 3))
            print('please modify your data')

        print("get_w(array).end...")
    # get_w(array)

    # def main(array)
    def mainAlgorithm(self, array):
        print("main(array).start...")

        if type(array) is np.ndarray:
            result = self.get_w(array)
            return result
        else:
            print('please input an instance of numpy')

        print("main(array).start...")
    # def main(array)

    # comparison_economic_function()
    def comparison_function(self):
        print("comparison_function(self).start...")

        e = np.array([
            [1,   2,   7,   5],
            [1/2, 1,   4,   3],
            [1/7, 1/4, 1,   2],
            [1/5, 1/4, 1/2, 1]
        ])

        a = self.comparison_matrix
        b = self.comparison_matrix
        c = self.comparison_matrix
        d = self.comparison_matrix
        f = self.comparison_matrix

        # print("e")
        e = self.mainAlgorithm(e)
        # print("e")

        # print("a")
        a = self.mainAlgorithm(a)
        # print("a")

        # print("b")
        b = self.mainAlgorithm(b)
        # print("b")

        # print("c")
        c = self.mainAlgorithm(c)
        # print("c")

        # print("d")
        d = self.mainAlgorithm(d)
        # print("d")

        try:
            print("try")

            # res = np.array([a, b, c, d, f])
            res = np.array([a, b, c, d])
            # print("res:")
            # print(res)

            resT = np.transpose(res)
            # print("resT:")
            # print(resT)
            # print("e:")
            # print(e)
            print("ret:")
            ret = (resT * e).sum(axis=1)
            print(ret)
            print("try.end: ret")
            return ret
        except TypeError:
            print('data error')

        print("comparison_function(self).end...")
    # comparison_function()
# class myAHP

# __main__
if __name__ == '__main__':
    print("MyAHP.py__main__.start...")
    ahp = myAHP()
    ahp.comparison_function()
    print("MyAHP.py__main__.end...")
# __main__


import random
import numpy as np

rand = random.SystemRandom()

def uniform(n, lower, upper):
    return np.array([rand.randint(lower, upper) for _ in range(n)], dtype=np.int)

class RLWE:
    def __init__(self, n, q):
        self.n = n
        self.q = q
        self.b = q // 2

    def generate_keys(self):
        s = uniform(self.n, -self.b, self.b)
        e = uniform(self.n, -self.b, self.b)
        a = uniform(self.n, 0, self.q)
        pub = (a * s + e) % self.q, a
        priv = s, e, a
        return pub, priv

    def sign(self, msg, priv):
        s, e, a = map(np.array, priv)
        msg = np.array(list(msg))
        y1 = uniform(self.n, -self.b, self.b)
        y2 = uniform(self.n, -self.b, self.b)
        w = (a*y1 + y2) % self.q
        c = (w + msg) % self.q
        z1 = (s*c + y1) % self.q
        z2 = (e*c + y2) % self.q
        return c, z1, z2

    def verify(self, msg, pub, sign):
        msg = np.array(list(msg))
        pub, a = map(np.array, pub)
        c, z1, z2 = map(np.array, sign)
        return all(c == ((a*z1 + z2 - pub*c) + msg) % self.q)


""" this script record useful functions """
import numpy as np
import matplotlib.pyplot as plt

#from scipy import fftpack

def transform_dft2(img, mode):
    ## convert to float
    img = img.astype(float)
    ## mean subtraction
    img = img - np.mean(img)
    ## rfft is different to fft
    if 'forward' in mode:
        ## 2d dft
        #img_dft = fftpack.fft2(img)
        img_dft = np.fft.fft2(img)
        ## shift to center
        img_dft_shifted = np.fft.fftshift(img_dft)
        return img_dft_shifted
    if 'inverse' in mode:
        img_dft_shifted = img
        ## shift to corner
        img_dft= np.fft.ifftshift(img_dft_shifted)
        ## 2d idft
        img = np.fft.rfft2(img_dft)
        return img

def cal_ringmean(img_fre):
    ## calculate ringing of 2d matrix from the center
    ## set the maximum spatial frequency
    res_max_spatial  = np.min([img_fre.shape[0],  img_fre.shape[1]])
    res_max_spatial_half = np.floor(res_max_spatial / 2).astype(int)
    ## calculate radial average of frequency coefficent
    coordinates_1d = np.arange(-res_max_spatial_half - 1, res_max_spatial_half, 1)
    coordinates_2d_x, coordinates_2d_y = np.meshgrid(coordinates_1d, coordinates_1d)
    radius_map = np.hypot(coordinates_2d_x, coordinates_2d_y)
    radius_map_floor = np.floor(radius_map)
    psd = np.zeros( (res_max_spatial_half + 1, 1) )

    for radius in range( res_max_spatial_half - 1):
        radius_loc = np.where(radius_map_floor == radius)
        coeffs = []
        #coeffs1 = img_fre_norm.take(radius_loc)
        coeffs = img_fre[radius_loc]
        psd[radius] = np.mean(coeffs)

    maxX = 10 ** (np.ceil(np.log10(float(res_max_spatial_half))));
    frequency = np.linspace(1, maxX, len(psd));
    frequency = (frequency) / (np.max(frequency)) / 2;
    return psd, frequency

def cal_auto_power_spectral_density(img_fre):
    img_fre_square = np.abs(img_fre ** 2)
    psd_auto, fre = cal_ringmean(img_fre_square)
    return psd_auto, fre

def cal_cross_power_spectral_density(img_fre, img_fre2):
    #img_fre_yx = np.multiply(img_fre2, np.conjugate(img_fre))
    img_fre_yx = np.multiply(img_fre2, img_fre)
    img_fre_xx = np.multiply(img_fre, img_fre)
    img_fre_cross = np.divide(img_fre_yx, img_fre_xx)
    psd_cross, fre = cal_ringmean(img_fre_cross)
    return psd_cross, fre

def cal_mtf_of_psd(coeff_src, coeff_ref, mode):
    ###
    if 'direct' in mode:
        coeff_src = coeff_src / np.max(coeff_src)
        coeff_ref = coeff_ref / np.max(coeff_ref)

        mtf = np.divide(coeff_src, coeff_ref)

    if 'cross' in mode:
       x=1

    return mtf


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

#Create data
x=np.array([0.,0.5,1.])
y_exact=np.array([0.,1.,1.])

#Intiliase W and b
W=0.5
b=0.5

#Set other constants
N=3
eta=0.01
MaxIter=16

#Initialise approximation
F=W * x + b

#Functions
def cost():
    return (1/N) * np.sum( 0.5* (y_exact - F)**2 )
#Partial derivates of cost
def cost_W(k):
    return (1/N) * np.sum( x[k]*(W*x[k]- y_exact[k] +b) )
def cost_b(k):
    return (1/N) * np.sum( W*x[k] - y_exact[k] + b )

#Cost_vec
cost_vec=np.empty(MaxIter)
j=np.arange(0,MaxIter,1)
w_vec=np.empty(MaxIter)
b_vec=np.empty(MaxIter)

#Peform stochastic gradient descent
for i in range(0,MaxIter):
    #Pick random index
    k=random.randint(0, (N-1))
    w_vec[i]=W
    b_vec[i]=b
    #Forward pass
    F=W*x+b
    #Alter weights and biases
    W= W - eta * cost_W(k)
    b= b - eta * cost_b(k)
    #Calculate newcost
    newcost=cost()
    cost_vec[i]=newcost

    #print(newcost)

plt.plot(j,cost_vec)
plt.title(f'Cost Eta={eta} MaxIter={MaxIter}')
plt.xlabel('Iteration')
plt.ylabel('Cost for SGD')
plt.show()

for i in range(0,MaxIter):
    print(f'{w_vec[i]} & {b_vec[i]} & {cost_vec[i]}')


import pandas as pd
import numpy as np
import theano.tensor as tt
import pymc3 as pm
import seaborn as sns
import matplotlib.pyplot as plt

iris = pd.read_csv('../data/iris.csv')

#######################
# single variable logit
#######################
df = iris.query("species == ('setosa', 'versicolor')")

y_0 = pd.Categorical(df['species']).codes
x_n = 'sepal_length'
x_0 = df[x_n].values
x_c = x_0 - x_0.mean()

# logistic regression
with pm.Model() as model_0:
    alpha = pm.Normal('alpha', mu=0, sd=10)
    beta = pm.Normal('beta', mu=0, sd=10)

    mu = alpha + pm.math.dot(x_c, beta)
    theta = pm.Deterministic('theta', pm.math.sigmoid(mu))

    bd = pm.Deterministic('bd', -alpha/beta)

    yl = pm.Bernoulli('yl', p=theta, observed=y_0)

    trace_0 = pm.sample(1000)

varnames = ['alpha', 'beta', 'bd']
pm.summary(trace_0, varnames)
pm.plot_trace(trace_0, varnames)

#######################
# multi variable logit
#######################

df = iris.query("species == ('setosa', 'versicolor')")
y_1 = pd.Categorical(df['species']).codes
x_n = ['sepal_length', 'sepal_width']
# note: not centering this time
x_1 = df[x_n].values

with pm.Model() as model_1:
    alpha = pm.Normal('alpha', mu=0, sd=10)
    beta = pm.Normal('beta', mu=0, sd=2, shape=len(x_n))

    mu = alpha + pm.math.dot(x_1, beta)

    # this time manually did it intead of pm.math.sigmoid
    theta = pm.Deterministic('theta', 1 / (1 + pm.math.exp(-mu)))

    bd = pm.Deterministic('bd', -alpha/beta[1] - beta[0]/beta[1] * x_1[:,0])

    yl = pm.Bernoulli('yl', p=theta, observed=y_1)

    trace_1 = pm.sample(2000)

varnames = ['alpha', 'beta']
pm.plot_forest(trace_1, var_names=varnames);

pm.summary(trace_1, ['alpha', 'beta'])

############################################
# multi variable logit w/ unbalanced classes
############################################

df = iris.query("species == ('setosa', 'versicolor')")
df = df[45:]
y_3 = pd.Categorical(df['species']).codes
x_n = ['sepal_length', 'sepal_width']
x_3 = df[x_n].values

with pm.Model() as model_3:
    alpha = pm.Normal('alpha', mu=0, sd=10)
    beta = pm.Normal('beta', mu=0, sd=2, shape=len(x_n))

    mu = alpha + pm.math.dot(x_3, beta)
    theta = 1 / (1 + pm.math.exp(-mu))
    bd = pm.Deterministic('bd', -alpha/beta[1] - beta[0]/beta[1] * x_3[:,0])

    yl = pm.Bernoulli('yl', p=theta, observed=y_3)

    trace_3 = pm.sample(1000)

###########################################
# softmax (logit but with multiple classes)
###########################################

iris = sns.load_dataset('iris')
y_s = pd.Categorical(iris['species']).codes
x_n = iris.columns[:-1]
x_s = iris[x_n].values
x_s = (x_s - x_s.mean(axis=0)) / x_s.std(axis=0)

with pm.Model() as model_s:
    # note alpha shape: 3 potential outputs
    alpha = pm.Normal('alpha', mu=0, sd=5, shape=3)
    # note beta shape: 4 explanatory variables, 3 potential outputs
    beta = pm.Normal('beta', mu=0, sd=5, shape=(4,3))

    mu = pm.Deterministic('mu', alpha + pm.math.dot(x_s, beta))

    theta = tt.nnet.softmax(mu)

    yl = pm.Categorical('yl', p=theta, observed=y_s)
    trace_s = pm.sample(2000)

data_pred = trace_s['mu'].mean(0)

y_pred = [np.exp(point)/np.sum(np.exp(point), axis=0)
          for point in data_pred]

f'{np.sum(y_s == np.argmax(y_pred, axis=1)) / len(y_s):.2f}'

###############################
# softmax with fewer parameters
###############################

with pm.Model() as model_sf:
    alpha = pm.Normal('alpha', mu=0, sd=2, shape=2)
    beta = pm.Normal('beta', mu=0, sd=2, shape=(4,2))
    alpha_f = tt.concatenate([[0] ,alpha])
    beta_f = tt.concatenate([np.zeros((4,1)) , beta], axis=1)
    mu = alpha_f + pm.math.dot(x_s, beta_f)
    theta = tt.nnet.softmax(mu)
    yl = pm.Categorical('yl', p=theta, observed=y_s)
    trace_sf = pm.sample(1000)

#####
# LDA
#####

with pm.Model() as lda:
    mu = pm.Normal('mu', mu=0, sd=10, shape=2)
    sigma = pm.HalfNormal('sigma', 10)
    # assuming sepal length normally distributed
    # put mu and sigma parameters on it - note: same sigma
    setosa = pm.Normal('setosa', mu=mu[0], sd=sigma, observed=x_0[:50])
    versicolor = pm.Normal('versicolor', mu=mu[1], sd=sigma,
                           observed=x_0[50:])
    # identifying bd, average of two means
    bd = pm.Deterministic('bd', (mu[0] + mu[1]) / 2)
    trace_lda = pm.sample(1000)

#######################
# zero-inflated poisson
#######################

n = 100
theta_real = 2.5
psi = 0.1

# Simulate some data
counts = np.array([(np.random.random() > (1-psi)) *
                   np.random.poisson(theta_real) for i in range(n)])

with pm.Model() as ZIP:
    # psi is prob being modeled by poisson
    # 1 - psi is prob of extra zeros
    psi = pm.Beta('psi', 1, 1)
    theta = pm.Gamma('theta', 2, 0.1)
    y = pm.ZeroInflatedPoisson('y', psi, theta,
                               observed=counts)
    trace = pm.sample(1000)

#######################################
# Poisson regression and ZIP regression
#######################################

fish_data = pd.read_csv('../data/fish.csv')

with pm.Model() as ZIP_reg:
    psi = pm.Beta('psi', 1, 1)
    alpha = pm.Normal('alpha', 0, 10)
    beta = pm.Normal('beta', 0, 10, shape=2)
    theta = pm.math.exp(alpha + beta[0] * fish_data['child'] + beta[1] *
                        fish_data['camper'])
    yl = pm.ZeroInflatedPoisson('yl', psi, theta, observed=fish_data['count'])
    trace_ZIP_reg = pm.sample(1000)

pm.plot_trace(trace_ZIP_reg)
pm.summary(trace_ZIP_reg)

############################
# Robust logistic regression
############################

iris = sns.load_dataset("iris")
df = iris.query("species == ('setosa', 'versicolor')")
y_0 = pd.Categorical(df['species']).codes
x_n = 'sepal_length'
x_0 = df[x_n].values
y_0 = np.concatenate((y_0, np.ones(6, dtype=int)))
x_0 = np.concatenate((x_0, [4.2, 4.5, 4.0, 4.3, 4.2, 4.4]))
x_c = x_0 - x_0.mean()

with pm.Model() as model_rlg:
    alpha = pm.Normal('alpha', mu=0, sd=10)
    beta = pm.Normal('beta', mu=0, sd=10)

    mu = alpha + x_c *  beta
    theta = pm.Deterministic('theta', pm.math.sigmoid(mu))
    bd = pm.Deterministic('bd', -alpha/beta)

    pi = pm.Beta('pi', 1., 1.)

    # saying prob is random (0.5) with prob pi, or logistic with 1-pi
    # way to do a robust logit
    p = pi * 0.5 + (1 - pi) * theta

    yl = pm.Bernoulli('yl', p=p, observed=y_0)

    trace_rlg = pm.sample(2000)


import tensorflow as tf
from scipy.ndimage import distance_transform_edt as eucl_distance
import numpy as np

def GDL_loss(y_true,y_pred):
    """
    Generalized Dice Loss
    y_true \in \mathbb{R}^{BxHxWxC}
    y_pred \in \mathbb{R}^{BxHxWxC}
    """
    eps= tf.constant(1e-20)
    y,y_hat = y_true,y_pred
    wG = 1/(tf.einsum('bijk->b',y)**2 - eps)
    wB = 1/tf.einsum('bijk->b',1-y)**2
    numerator = wG*tf.einsum('bijk,bijk->b',y,y_hat) + wB* tf.einsum('bijk,bijk->b',1-y,1-y_hat)
    denominator = wG*tf.einsum('bijk->b',y+y_hat) + wB*tf.einsum('bijk->b',2-y-y_hat)

    return  tf.reduce_mean(1 - 2*(numerator+eps)/(denominator+eps))

def distmaps(y_true):
    k = tf.shape(y_true)[0]
    res = np.zeros_like(y_true,dtype=np.float32)
    for i in range(k):
        posmask = y_true[i,...] > 0.5
        negmask = ~ posmask
        res[i,...] = tf.cast(eucl_distance(negmask),dtype=tf.float32)* tf.cast(negmask,tf.float32) -tf.cast(eucl_distance(posmask),dtype=tf.float32)*tf.cast(posmask,tf.float32)
    return res

def boundary_loss(y_true,y_pred):
    """
    Boundary loss
    y_true \in \mathbb{R}^{BxHxW}
    y_pred \in \mathbb{R}^{BxHxW}
    """
    dist_map = tf.py_function(func=distmaps, inp=[y_true], Tout=tf.float32) # tensor [batch,h,w]
    value = tf.einsum('ijlk,ijlk->i',dist_map,y_pred) #- tf.einsum('ijk,ijk->i',dist_map,y_true)  # tensor[batch]
    return tf.reduce_mean(value)#/tf.reduce_sum(tf.abs(dist_map))

def Dice_metric(y_true,y_pred):
    B = tf.shape(y_true)[0]
    res = 0.0
    for b in range(B):
        if tf.reduce_sum(y_true[b]) == 0:
            continue
        y, y_hat = y_true[b] , y_pred[b]
        intersection = tf.einsum('ijk,ijk->',y,y_hat) #haddamar -> sum j and k for each image
        union = tf.einsum('ijk->',y**2) + tf.einsum('ijk->',y_hat**2) #sum  j and k
        res +=  2*intersection/union # dice per image
    return res/tf.cast(B,tf.float32)

def Dice_loss(y_true,y_pred):
    nue = 2*tf.reduce_sum(y_true*y_pred)
    den = tf.reduce_sum(y_true**2) + tf.reduce_sum(y_pred**2)
    return 1-nue/den


def norm_eqn_fit(x,y):
     import numpy as np
     import matplotlib.pyplot as plt
     N=y.size
     D=len(x.shape)
     #SIMPLE LINEAR REGRESSION
     if D==1:
         dummy=np.array([[1]*N]).T
         X = np.column_stack((dummy,x))
         w=np.linalg.solve(X.T.dot(X),X.T.dot(y))
         yhat=X.dot(w)
         R2=1-np.sum((y-yhat)**2)/np.sum((y-y.mean())**2)
         fig=plt.figure()
         plt.scatter(x,y,color = "green")
         plt.plot(x,yhat)
         weights="Weights are: "
         Rsquared="Rsquared is: "
         result=( [weights, w],[Rsquared, R2],fig)

         return result

     #MULTIPLE LINEAR REGRESSION
     else:
         dummy=np.array([[1]*N]).T
         X = np.column_stack((dummy,x))
         w=np.linalg.solve(X.T.dot(X),X.T.dot(y))
         yhat=X.dot(w)
         R2=1-np.sum((y-yhat)**2)/np.sum((y-y.mean())**2)
         weights="Weights are: "
         Rsquared="Rsquared is: "
         result=( [weights, w],[Rsquared, R2])

         return result

def grad_descnt_fit(x,y,eta=0.01,epoch=2000,lmda_l2=0,lmda_l1=0):

    import numpy as np
    import matplotlib.pyplot as plt
    N=y.size
    D=x.shape[1]
    #SIMPLE LINEAR REGRESSION
    if D==1:
         dummy = np.array([[1]*N]).T
         X  = np.column_stack((dummy,x))
         #w = np.random.randn(D+1)
         w = np.array([np.random.randn(D+1)]).T
         J = []
         for t in range(epoch):
              yhat = X.dot(w)

              J.append(np.dot((y - yhat).T,y - yhat))
              w-=eta * X.T.dot(yhat-y)
         yhat = X.dot(w)

         R2=1-np.sum((y-yhat)**2)/np.sum((y-y.mean())**2)
         fig=plt.figure()
         plt.scatter(x,y,color = "green")
         plt.plot(x,yhat)
         weights="Weights are: "
         Rsquared="Rsquared is: "
         result=( [weights, w],[Rsquared, R2],fig)

         return result

    else:
        #MULTIPLE LINEAR REGRESSION
          dummy = np.array([[1]*N]).T
          X  = np.column_stack((dummy,x))
          w = np.random.randn(D+1)
          J = []
          for t in range(epoch):
               yhat = X.dot(w)
               J.append(np.dot((y - yhat).T,y - yhat))
               w-=eta * X.T.dot(yhat-y)
          yhat = X.dot(w)
          R2=1-np.sum((y-yhat)**2)/np.sum((y-y.mean())**2)
          weights="Weights are: "
          Rsquared="Rsquared is: "
          fig=plt.figure()
          plt.plot(J)
          result=( [weights, w],[Rsquared, R2],fig)

          return result

def predict(fit,x,y):
    import numpy as np
    import matplotlib.pyplot as plt
    #SIMPLE LINEAR PREDICTION
    D=len(fit[0][1])
    if D==2:
        yhat=fit[0][1][0]+x*fit[0][1][1]
        R2=1-np.sum((y-yhat)**2)/np.sum((y-y.mean())**2)
        fig=plt.figure()
        plt.scatter(x,y,color = "green")
        plt.plot(x,yhat)
        Rsquared="Rsquared is: "
        pred="Predictions are: "
        act="Actual Values are: "

        result=([Rsquared, R2],[act,y],[pred,yhat],fig)
        return result
    #MULTIPLE LINEAR PREDICTION
    else:
        N=len(y)
        w=fit[0][1].T
        dummy = np.array([[1]*N]).T
        X  = np.column_stack((dummy,x))
        yhat=X.dot(w)
        R2=1-np.sum((y-yhat)**2)/np.sum((y-y.mean())**2)
        Rsquared="Rsquared is: "
        relerror =np.abs((y - yhat) / y)
        mre=np.median(relerror)
        MRE= "Median Relative Error: "
        act="Actual Values are: "
        pred="Predictions are: "
        result=( [MRE, mre],[Rsquared, R2],[act,y],[pred,yhat])

        return result


import numpy as np
import tensorflow as tf

# 출석일수, 공부한시간
x_data = np.array([[1., 3.],
                   [2., 2.],
                   [3., 1.],
                   [4., 6.],
                   [5., 5.],
                   [6., 4.]])

y = np.array([[0], [0], [0], [1], [1], [1]])

print(x_data.shape)
print(y.shape)

X = tf.placeholder(tf.float32)
W = tf.Variable(tf.random_uniform([2, 1]))
b = tf.Variable(tf.random_uniform([1]))

z = tf.matmul(X, W) + b
hx = tf.sigmoid(z)

cost_i = y * (-tf.log(hx)) + (1 - y) * (-tf.log(1 - hx))
cost = tf.reduce_mean(cost_i)
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.1)
train = optimizer.minimize(cost)

sess = tf.Session()
init = tf.global_variables_initializer()
sess.run(init)

for i in range(1000):
    _t, _c = sess.run([train, cost], feed_dict={X: x_data})
    if not i % 100:
        print(i, _c)

print(sess.run(W))
print(sess.run(b))

print(sess.run(z, feed_dict={X: np.array([[3., 5.]])}))
print(sess.run(hx, feed_dict={X: np.array([[3., 5.], [1., 1.]])}))

result = sess.run(hx, feed_dict={X: np.array([[3., 5.], [1., 1.]])})

# True -> 1 False -> 0
result1 = tf.cast(result > 0.5, dtype=np.int32)
print(sess.run(result1))


"""ARCH(1) model:

r_t = log(p_t) - log(p_(t-1))
r_t = s_t * e_t
s_t^2 = w + a * r_t^2
"""
from pprint import pprint
import numpy as np
from scipy.optimize import lsq_linear
import matplotlib.pyplot as plt
from time_series_model_template import TimeSeriesModel

class Arch1(TimeSeriesModel):
    def __init__(self):
        self.omega = None
        self.alpha = None

    def fit_parameters(self, dt, x):
        # least square method
        # E[r_t^2] = w + a * r_(t-1)^2
        r2 = x ** 2
        ones = np.ones_like(r2[1:])
        opt_result = lsq_linear(np.column_stack((ones, r2[:-1])), r2[1:])
        if opt_result.success:
            self.omega, self.alpha = opt_result.x
            pprint(self.parameters)
        else:
            pprint(opt_result)

    def simulate(self, x0, t):
        x = np.zeros_like(t)
        x[0] = x0
        w, a = self.omega, self.alpha
        for i in range(1, len(t)):
            s = np.sqrt(w + a * x[i-1] ** 2)
            x[i] = np.random.randn() * s
        return x

def main():
    np.random.seed(0)
    a_model = Arch1()
    a_model.omega = 1e-4
    a_model.alpha = 0.3
    dt = 1
    t = np.arange(0, 5000., dt)
    x = a_model.simulate(0, t)
    a_model.fit_parameters(dt, x)
    y = a_model.simulate(0, t)
    plt.plot(t, x.cumsum())
    plt.plot(t, y.cumsum())
    plt.show()

if __name__ == "__main__":
    main()


import numpy as np
from kmeans import kmeans
import matplotlib as mpl
mpl.use('TkAgg')
import matplotlib.pyplot as plt

center_1 = np.array([1,1])
center_2 = np.array([5,5])
center_3 = np.array([8,1])

# Generate random data and center it to the three centers
data_1 = np.random.randn(200, 2) + center_1
data_2 = np.random.randn(200,2) + center_2
data_3 = np.random.randn(200,2) + center_3

data = np.concatenate((data_1, data_2, data_3), axis = 0)

# Number of clusters
k = 3
# Number of training data
n = data.shape[0]
# Number of features in the data
c = data.shape[1]

# Generate random centers, here we use sigma and mean to ensure it represent the whole data
mean = np.mean(data, axis = 0)
std = np.std(data, axis = 0)
centers = np.random.randn(k,c)*std + mean

# Plot the data and the centers generated as random
plt.scatter(data[:,0], data[:,1], s=7)
plt.scatter(centers[:,0], centers[:,1], marker='*', c='g', s=150)
plt.title('before')
plt.show()

kmeans(data, centers, k)

# Plot the data and the centers generated as random
plt.scatter(data[:,0], data[:,1], s=7)
plt.scatter(centers[:,0], centers[:,1], marker='*', c='g', s=150)
plt.show()
plt.title('after')
print('new centers', centers)


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

import itertools
import numpy as np

def entropy(*X):
    """
    Calculate the entropy of a variable, or joint entropy of several variables.

    Parameters
    ----------
    X : array, or list of arrays
        Variable or variables to compute entropy/joint entropy on

    Notes
    -----
    This function can be used to calculate the entropy of a single variable
    (provided as a single input) or to calculate the joint entropy between two
    variables (provided as a series of inputs)
    """
    n_instances = len(X[0])
    H = 0
    for classes in itertools.product(*[set(x) for x in X]):
        v = np.array([True] * n_instances)
        for predictions, c in zip(X, classes):
            v = np.logical_and(v, predictions == c)
        p = np.mean(v)
        H += -p * np.log2(p) if p > 0 else 0
    return H

def conditional_entropy(x, y):
    """
    The conditional entropy H(X|Y) = H(Y,X) - H(Y). X conditioned on Y
    """
    H_y = entropy(y)
    H_yx = entropy(y, x)
    return H_yx - H_y

def mutual_information(x, y):
    """
    The mutual information between two variables

    MI(X, Y) = H(X) + H(Y) - H(X | Y)

    Parameters
    ----------
    x, y : array

    Returns
    -------
    array : mutual information between x and y
    """
    H_x = entropy(x)
    H_y = entropy(y)
    H_xy = entropy(x, y)
    return H_x + H_y - H_xy

def entropy_cc(x, y):
    """
    The entropy correlation coefficient:

    p(H) = sqrt(MI(X, Y) / 0.5 * (H(X) + H(Y)))
    """
    H_x = entropy(x)
    H_y = entropy(y)
    I_xy = mutual_information(y, x)
    return np.sqrt(I_xy / (0.5 * (H_x + H_y)))

def transfer_entropy(x, y, lag=1):
    """
    Transfer entropy for two given signals.

    Parameters
    ----------
      x : array
        source
      y : array
        target
      lag : int

    Returns
    -------
    array : Transfer entropy from x to y
    """
    # Future of i
    Fi = np.roll(x, -lag)
    # Past of i
    Pi = x
    # Past of j
    Pj = y

    # Transfer entropy
    Inf_from_Pi_to_Fi = conditional_entropy(Fi, Pi)

    # Same as cond_entropy(Fi, Pi_Pj)
    H_y = entropy(Pi, Pj)
    H_yx = entropy(Fi, Pj, Pi)
    Inf_from_Pi_Pj_to_Fi = H_yx - H_y

    TE_from_j_to_i = Inf_from_Pi_to_Fi - Inf_from_Pi_Pj_to_Fi

    return TE_from_j_to_i