import numpy as np
from scipy.interpolate import CubicSpline

def gen_c2_spline(x, y, init_heading, slen_start, slen_end):
    '''
    Generates a C2 continuous spline using scipy CubicSpline lib
    x: np.array of x-coordinate points
    y: np.array of y-coordinate points
    '''

    # define mu, a virtual path variable of length 1 for each spline segment
    assert(len(x) == len(y))
    mu = np.arange(0,len(x), 1.0)

    # build splines
    cs_x = CubicSpline(mu, x,
                   bc_type=((1, slen_start * np.cos(init_heading)),
                            (2, 0.0)))
    cs_y = CubicSpline(mu, y,
                   bc_type=((1, slen_start * np.sin(init_heading)),
                            (2, 0.0)))
    return cs_x, cs_y

def calc_c2_traj(x, y, init_heading, eps = 0.005):
    '''
    Iteratively compute spline coefficients until spline length of first and last segment converges
    x, y: 1D numpy array of control coordinates (x,y) through which spline must pass
    '''

    # Start with euclidean dist as slen approx for first and last segments
    slen_start = np.sqrt((x[1] - x[0])**2 + (y[1] - y[0])**2)
    slen_end = np.sqrt((x[-1] - x[-2])**2 + (y[-1] - y[-2])**2)

    while True:
        cx, cy = gen_c2_spline(x, y, init_heading, slen_start, slen_end)
        coeffs_x_start = np.flip(cx.c[:,0])
        coeffs_y_start = np.flip(cy.c[:,0])
        coeffs_x_end = np.flip(cx.c[:,-1])
        coeffs_y_end = np.flip(cy.c[:,-1])

        slen_start_new = calc_spline_length(coeffs_x_start, coeffs_y_start)
        slen_end_new = calc_spline_length(coeffs_x_end, coeffs_y_end)

        if abs(slen_start_new - slen_start) < eps and abs(slen_end_new - slen_end) < eps:
            break
        else:
            slen_start = slen_start_new
            slen_end = slen_end_new
    return cx, cy

def calc_spline_length(x_coeffs, y_coeffs, n_ips=100):
    '''
    Returns numerically computed length along cubic spline
    x_coeffs: array of 4 x coefficients
    y_coeffs: array of 4 y coefficients
    '''

    t_steps = np.linspace(0.0, 1.0, n_ips)
    spl_coords = np.zeros((n_ips, 2))

    spl_coords[:,0] = x_coeffs[0] \
                        + x_coeffs[1] * t_steps \
                        + x_coeffs[2] * np.power(t_steps, 2) \
                        + x_coeffs[3] * np.power(t_steps, 3)
    spl_coords[:,1] = y_coeffs[0] \
                        + y_coeffs[1] * t_steps \
                        + y_coeffs[2] * np.power(t_steps, 2) \
                        + y_coeffs[3] * np.power(t_steps, 3)

    slength = np.sum(np.sqrt(np.sum(np.power(np.diff(spl_coords, axis=0), 2), axis=1)))
    return slength

def compute_spline_heading(x, y, t):
    '''
    Evaluate heading (psi) using parametric spline representation at each interpolated point in t
    Ensure returned angles are between [-pi, pi]
        t = path variable, a 1D numpy array

    '''
    psi = np.arctan2(y(t,1), x(t,1))
    psi[psi >= np.pi] -= 2 * np.pi
    psi[psi < -np.pi] += 2 * np.pi
    return psi

def compute_spline_curvature(x, y, t):
    '''
    Evaluate K using parametric curvature equation at each point in t
        Splines are given as parametric equations: x = x(t), y = y(t)
        t = path variable, a 1D numpy array
    Returns an array of curvatures along the spline with same shape as t
    '''
    K = np.abs( x(t,1)*y(t,2) - y(t,1)*x(t,2) ) / ( (x(t,1)**2) + y(t,1)**2 )**(3/2)
    return K


x = [1, 2, 3, 4]
y = [5, 6, 7, 8]
print( x * 2 )

import numpy as np
ax = np.array([1, 2, 3, 4])
ay = np.array([5, 6, 7, 8])
print( ax * 2, ax+2 ,ax + ay, ax * ay )

def f(x):
    return 3*x**2 - 2*x+7

print( f(ax) )
print( np.sqrt( ax ) )
print( np.cos(ax) )

grid = np.zeros( shape=(10000,10000),dtype=float )
print(grid)
grid += 10
print( grid )
print( np.sin(grid) )

a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
print(a)
#a row 1,start at 0
print(a[1])
#a column 1,start at 0
print(a[:,1])
print(a[1:3,1:3])
# Select a subregion and change it
a[1:3,1:3] += 10
print( a )

# Broadcast a row vector across an operation on all rows
print( a + [100, 101, 102, 103])
# Conditional assignment on an array
# if all the array are 1-D ,where is equivalent to :
#[xv if c else yv for c, xv,yv in zip( condition, x, y)]
print( np.where(a<10,a, 10))
"""
[[ 1  2  3  4]
 [ 5 10 10  8]
 [ 9 10 10 10]]
"""

chapter3/3_9Calculating with Large Numerical Arrays/3_9.py


'''
This script provides utility functions estimating angular velocities
and other physical quantities from angles of single pendulum.
'''

import numpy as np
from scipy.interpolate import CubicSpline

# physical parameters
fps = 60  # frames per second
l = 0.5   # pendulum rod length (m)
m = 1.0   # bob mass (kg)
g = 9.81  # gravitational acceleration (m/s^2)

'''
Calculate the absolute difference between two angles th1 and th2 on a circle.
Assumed that the absolute difference between the two angles is within range (0,pi).
'''
def calc_diff(th1, th2):
    diff = np.abs(th2 - th1)
    diff = np.minimum(diff, 2*np.pi-diff)
    return diff

'''
Calculate the average of two angles th1 and th2 on a circle.
Assumed that the absolute difference between the two angles is within range (0,pi).
'''
def calc_avrg(th1, th2):
    avrg = (th1 + th2) / 2
    diff = np.abs(th2 - th1)
    if diff > np.pi:
        avrg -= np.pi
    if avrg < 0:
        avrg += 2*np.pi
    return avrg

'''
Normalize the angle to (-pi, pi).
'''
def normalize_angle(theta):
    return np.arctan2(np.sin(theta), np.cos(theta))

'''
Calculate angular velocities from a sequence of angles
using numerical differentiation.
method='fd': finite difference;
method='spline': cubic spline fitting.
'''
def calc_velocity(th, method='spline'):
    len_seq = th.shape[0]

    # isolated data
    if len_seq == 1:
        return np.nan

    # preprocessing: periodic extension of angles
    for i in range(1, len_seq):
        if th[i] - th[i-1] > np.pi:
            th[i:] -= 2*np.pi
        elif th[i] - th[i-1] < -np.pi:
            th[i:] += 2*np.pi

    vel_th = np.zeros(len_seq)

    # finite difference
    if method == 'fd':
        for i in range(1, len_seq):
            vel_th[i] = (th[i] - th[i-1]) * fps
        vel_th[0] = (th[1] - th[0]) * fps

    # cubic spline fitting
    elif method == 'spline':
        t = np.arange(len_seq) / fps
        cs = CubicSpline(t, th)
        vel_th = cs(t, 1)
        # use finite difference at boundary points to improve accuracy
        vel_th[0] = (th[1] - th[0]) * fps
        vel_th[-1] = (th[-1] - th[-2]) * fps

    else:
        assert False, 'Unrecognizable differentiation method!'

    return vel_th

'''
Calculate energies from angles and angular velocities
Moment of inertia of the pendulum: I=ml^2/3
'''
def calc_energy(th, vel_th):
    T = m * l**2 / 6 * vel_th**2
    V = - m * g * l / 2 * np.cos(th)
    E = T + V
    return T, V, E


from itertools import accumulate
import numpy as np
import matplotlib.pyplot as plt

def mass_spring(x, u, dt=0.05, m=1, c=2, k=1):
    """Mass-spring-damper system
    x  :: state variables (x1, x2) where
         x1 = position (m)
         x2 = velocity (m/s)
    u  :: input force (N)
    dt :: timestep (s)
    m  :: mass (kg)
    c  :: damping coefficient (Ns/m)
    k  :: spring constant (N/m)
    """
    dxdt = (x[1], (-k*x[0] - c*x[1] + u) / m)
    return x[0] + dt*dxdt[0], x[1] + dt*dxdt[1]

def plot_trajectory(t, x, u, title=None):
    fig, axes = plt.subplots(2, 1, sharex=True)
    axes[0].plot(t, [x[0] for x in x_sol], label='$x_1(t)$')
    axes[0].plot(t, [x[1] for x in x_sol], label='$x_2(t)$')
    axes[0].legend()
    axes[0].grid()
    axes[0].set_title(title)
    axes[1].step(t[:-1], u, label='$u(t)$')
    axes[1].legend()
    axes[1].grid()
    axes[1].set_xlabel('t')
    plt.show()

# Unit tests
# Mass spring
assert mass_spring((0.0, 0.0), 0.0) == (0.0, 0.0)
dt, m, c, k = (0.1, 1, 0.2, 1)
x1 = mass_spring((0.0, 0.0), 0.2, dt, m=m, c=c, k=k)
assert np.allclose(x1, (0.0, 0.02))
x1 = mass_spring((0.2, 0.0), 0.0, dt, m=m, c=c, k=k)
assert np.allclose(x1, (0.2, -0.02))
x1 = mass_spring((0.0, 0.2), 0.0, dt, m=m, c=c, k=k)
assert np.allclose(x1, (0.02, 0.196))

# Simulation with forcing
x0 = (0.0, 0.0)
nT = 200  # number of timesteps
t_sim = np.linspace(0, 10, nT + 1)
u_sim = np.zeros(nT)
u_sim[0:25] = 1  # Add force for short period

# Solve recurrence equation
x_sol = list(accumulate(u_sim, mass_spring, initial=x0))
assert len(x_sol) == nT + 1
plot_trajectory(t_sim, x_sol, u_sim, title="Mass-Spring Damper")


import os
import numpy as np
path = os.path.dirname(os.path.realpath(__file__))

def risk_level(lines:list):
    data = [[int(i) for i in list(line.strip())] for line in lines]
    arr = np.array(data, dtype='int32')
    l = len(arr)
    w = len(arr[0])
    risk = 0
    for i in range(l):
        for k in range(w):
            is_low = True
            if i-1>=0:
                if arr[i,k]>=arr[i-1,k]:
                    is_low = False
            if k-1>=0:
                if arr[i,k]>=arr[i,k-1]:
                    is_low = False
            if i+1<l:
                if arr[i,k]>=arr[i+1,k]:
                    is_low = False
            if k+1<w:
                if arr[i,k]>=arr[i,k+1]:
                    is_low = False
            if is_low:
                risk += arr[i,k]+1

    return risk

def basins(lines:list):

    def check_point_passed(i, k, points):
        for (a,b) in points:
            if a==i and b==k:
                return True
        return False

    def calc_basin(arr, i, k, val, points):
        if not check_point_passed(i, k, points):
            if i>=0 and i<len(arr) and k>=0 and k<len(arr[0]):
                if 9 > arr[i,k] > val:
                    points.append((i,k))
                    res = 1
                    res += calc_basin(arr, i+1, k, arr[i,k], points)
                    res += calc_basin(arr, i-1, k, arr[i,k], points)
                    res += calc_basin(arr, i, k+1, arr[i,k], points)
                    res += calc_basin(arr, i, k-1, arr[i,k], points)
                    return res
        return 0

    data = [[int(i) for i in list(line.strip())] for line in lines]
    arr = np.array(data, dtype='int32')
    l = len(arr)
    w = len(arr[0])

    top = [0,0,0]
    for i in range(l):
        for k in range(w):
            points = []
            c = calc_basin(arr, i, k, -1, points)
            #print(c, points)
            if c > min(top):
                top.pop(top.index(min(top)))
                top.append(c)

    return top[0]*top[1]*top[2]

test_lines = [
    '2199943210',
    '3987894921',
    '9856789892',
    '8767896789',
    '9899965678',
]

lines = []
with open(path+"/input.txt") as file:
    lines = file.readlines()
    lines = [line.strip() for line in lines]

assert risk_level(test_lines) == 15, "Function is wrong"
print("Part A:", risk_level(lines))
assert basins(test_lines) == 1134, "Function is wrong"
print("Part B:", basins(lines))


"""Monte Carlo Model"""
__docformat__ = "numpy"

import logging
from typing import Union

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

from openbb_terminal.decorators import log_start_end

logger = logging.getLogger(__name__)

DISTRIBUTIONS = ["normal", "lognormal"]

@log_start_end(log=logger)
def get_mc_brownian(
    data: Union[pd.Series, np.ndarray], n_future: int, n_sims: int, use_log=True
) -> np.ndarray:
    """Performs monte carlo forecasting for brownian motion with drift

    Parameters
    ----------
    data : Union[pd.Series, np.ndarray]
        Input data.
    n_future : int
        Number of future steps
    n_sims : int
        Number of simulations to run
    use_log : bool, optional
        Flag to use log returns, by default True

    Returns
    -------
    np.ndarray
        Array of predictions.  Has shape (n_future, n_sims)
    """

    changes = data.pct_change().dropna()  # type: ignore

    if use_log:
        changes = np.log(1 + changes)

    dist_mean = changes.mean()
    dist_var = changes.var()
    dist_drift = dist_mean - 0.5 * dist_var
    dist_std = np.sqrt(dist_var)

    random_steps = norm.ppf(np.random.rand(n_future, n_sims))
    predicted_change = np.exp(dist_drift + dist_std * random_steps)
    possible_paths = np.zeros_like(predicted_change)
    possible_paths[0] = data.values[-1]  # type: ignore

    for t in range(1, n_future):
        possible_paths[t] = possible_paths[t - 1] * predicted_change[t]

    return possible_paths


# Generated on: 2021-08-13
# Author: Suwon Lee from Samsung Electronics

import numpy as np
import scipy
from scipy.special import comb

class Bernstein:
    def __init__(self,coef):
        self.coefficients = coef
        self.n = np.size(coef) - 1

    def basis(self,n,i,x):
        return comb(n,i)*x**i*(1-x)**(n-i)

    def basisPthDerivative(self,n,i,p,x):
        DpBin = 0
        for k in range(max(0,i+p-n),max(i,p)+1):
            term = (-1)**(k+p)*comb(p,k)*self.basis(n-p,i-k,x)
            DpBin = DpBin + term
        return scipy.special.factorial(n)/scipy.special.factorial(n-p)*DpBin

    def feval(self,x):
        n = self.n
        nx = np.size(x)
        value = np.zeros(nx)
        for i in range(1,n+1+1):
            v = i-1
            value = value + self.basis(n,v,x)*self.coefficients[v]
        return value

    def derivative(self,x):
        n = self.n
        nx = np.size(x)
        value = np.zeros(nx)
        for i in range(1,n+1+1):
            v = i-1
            value = value + self.basisPthDerivative(n,v,1,x)*self.coefficients[v]
        return value

    def Pthderivative(self,x,P):
        n = self.n
        nx = np.size(x)
        value = np.zeros(nx)
        for i in range(1,n+1+1):
            v = i-1
            value = value + self.basisPthDerivative(n,v,P,x)*self.coefficients[v]
        return value


import numpy as np
import scipy.signal as sp
import matplotlib.pyplot as plt

def one_sided_fft(t, x):
    full_amplitude_spectrum = np.abs(np.fft.fft(x))/x.size
    full_freqs = np.fft.fftfreq(x.size, np.mean(np.ediff1d(t)))
    oneinds = np.where(full_freqs >= 0.0)
    one_sided_freqs = full_freqs[oneinds]
    one_sided_amplitude_spectrum = 2*full_amplitude_spectrum[oneinds]
    return one_sided_freqs, one_sided_amplitude_spectrum

def power_spectrum(t, x):
    onef, oneamps = one_sided_fft(t, x)
    return onef, oneamps**2

def lomb_scargle_pspec(t, x):
    tstep = np.mean(np.ediff1d(t))
    freqs = np.fft.fftfreq(x.size, tstep)
    idxx = np.argsort(freqs)
    one_sided_freqs = freqs[idxx]
    one_sided_freqs = one_sided_freqs[one_sided_freqs > 0]
    # KLUDGE TO KEEP PERIODOGRAM FROM CRASHING
    one_sided_freqs = one_sided_freqs+0.00001 * \
        np.random.random(one_sided_freqs.size)
    # THE FOLLOWING LINE CRASHES WITHOUT THE KLUDGE
    pgram = sp.lombscargle(t, x, one_sided_freqs*2*np.pi)
    return one_sided_freqs, (pgram/(t.size/4))

# Sample data
# fs = 50
# fund_freq = 5
# ampl = 0.4
# t = np.arange(0, 1, 1/fs)
# x = ampl*np.cos(2*np.pi*fund_freq*t)

# Sample data
fs = 1
fund_freq = 1/365
ampl = 0.4
t = np.arange(0, 3650, 1/fs)
x = ampl*np.cos(2*np.pi*fund_freq*t)

# power spectrum calculations
# powerf, powerspec = power_spectrum(t, x)
full_amplitude_spectrum = np.abs(np.fft.fft(x))/x.size
full_freqs = np.fft.fftfreq(x.size, np.mean(np.ediff1d(t)))

oneinds = np.where(full_freqs >= 0.0)
one_sided_freqs = full_freqs[oneinds]
one_sided_amplitude_spectrum = 2*full_amplitude_spectrum[oneinds]
powerf = one_sided_freqs
powerspec = one_sided_amplitude_spectrum**2

# power spectrum calculations
# lsf, lspspec = lomb_scargle_pspec(t, x)
tstep = np.mean(np.ediff1d(t))
freqs = np.fft.fftfreq(x.size, tstep)
idxx = np.argsort(freqs)
one_sided_freqs = freqs[idxx]
one_sided_freqs = one_sided_freqs[one_sided_freqs > 0]
pgram = sp.lombscargle(t, x, one_sided_freqs*2*np.pi)
lsf = one_sided_freqs
lspspec = (pgram/(t.size/4))

# plotting
fig, (ax0, ax1, ax2) = plt.subplots(nrows=3)
fig.tight_layout()
ax0.plot(t, x)
ax0.set_title('Input Data, '+str(fund_freq)+' Hz, ' +
              'Amplitude: '+str(ampl) +
              ' Fs = '+str(fs)+' Hz')
ax0.set_ylabel('Volts')
ax0.set_xlabel('Time[s]')

ax1.plot(powerf, powerspec,'-*')
ax1.set_title('FFT-based Power Spectrum')
ax1.set_ylabel('Volts**2')
ax1.set_xlabel('Freq[Hz]')

ax2.plot(lsf, lspspec,'-*')
ax2.set_title('Lomb-Scargle Power Spectrum')
ax2.set_ylabel('Volts**2')
ax2.set_xlabel('Freq[Hz]')

plt.show()


""" Two-sample difference tests.

Author:

    C.M. Gosmeyer

Date:

    Mar 2018

References:

    "Introduction to Statistical Problem Solving in Geography",
    J.C. McGrew, Jr., A.J. Lembo, Jr., C.B. Monroe

"""

import numpy as np

class DiffOfMeans(object):
    """ Base class for two-sample difference of means tests.
    """
    def __init__(self, n1, n2):

        """
        Parameters
        ----------
        n1 : int
            Size of sample 1.
        n2 : int
            Size of sample 2.
        """

        self.n1 = float(n1)
        self.n2 = float(n2)
        self.test_stat = None

    def get_test_stat(self):
        print(self.test_stat)

class ZTest(DiffOfMeans):
    """ Compares two independent random sample means for difference.

    Requirements
    ------------
    1. Two independent random samples.
    2. Each population normally distributed. (i.e., follows Z
       distribution)
    3. Variable is measured at interval or ratio scale.

    Null Hypthothesis
    -----------------
    population mean 1 = population mean 2

    Test Statistic
    --------------

        1. If SampleSize >= 30 and variances of both populations known:

        Z = SampleMean1 - SampleMean2 / StandardErrorOfDifferenceOfMeans

        where

        StandardErrorOfDifferenceOfMeans = sqrt( (StandErr1^2 / NumberSamples1) +
                                                 (StandErr2^2 / NumberSamples2) )

        2. If SampleSize < 30 and variances of populations *unknown* but assumed *equal*:

        t = SampleMean1 - SampleMean2 / StandardErrorOfDifferenceOfMeans

        where

        StandardErrorOfDifferenceOfMeans = PVE * sqrt( (1 / NumberSamples1) +
                                                       (1 / NumberSamples2) )

        where

        PVE = sqrt( [SampleVariance1^2 * (NumberSamples1 - 1) +
                     SampleVariance2^2 * (NumberSamples2 - 1)] \
                    [NumberSamples1 + NumberSamples2 - 2] )

        3. If SampleSize < 30 and variances of populations *unknown* but
        assumed *unequal*:

        SVE = StandardErrorOfDifferenceOfMeans
            = sqrt( (SampleVariance1^2 / NumberSamples1) +
                    (SampleVariance2^2 / NumberSamples2) )
    """
    def __init__(self, n1, n2, mean1, mean2, s1, s2, sigma1=None, sigma2=None):
        DiffOfMeans.__init__(self, n1, n2)
        """
        Parameters
        ----------
        mean1 : float
            Mean of sample 1.
        mean2 : float
            Mean of sample 2.
        s1 : float
            Variance of sample 1.
        s2 : float
            Variance of sample 2.
        sigma1 : float
            Variance of population 1, if known.
        sigma2 : float
            Variance of population 2, if known.
        """
        self.mean1 = mean1
        self.mean2 = mean2
        self.s1 = s1
        self.s2 = s2
        self.sigma1 = sigma1
        self.sigma2 = sigma2
        self.Z = None
        self.t = None
        self.sigma_x1subx2 = None
        self.test_stat = None
        self.test_statistic()

    def standard_error(self, var1, var2):
        """ Calculates standard error of difference of means.
        """
        if self.sigma1 != None and self.sigma2 != None:
            sigma_x1subx2 = np.sqrt( (var1**2 / self.n1) + (var2**2 / self.n2) )

        elif var1 == var2:
            PVE = np.sqrt( (var1**2 * (self.n1 - 1) + var2**2 * (n2 - 1)) / \
                            (self.n1 + self.n2 - 2) )
            sigma_x1subx2 = PVE * np.sqrt( (1 / self.n1) + (1 / self.n2) )

        elif var1 != var2:
            SVE = np.sqrt( (var1**2 / self.n1) + (var2**2 / self.n2) )
            sigma_x1subx2 = SVE

        return sigma_x1subx2

    def test_statistic(self):
        """ Calculates test statistic.

        Should it return whether used Z or t?
        """
        if self.sigma1 != None and self.sigma2 != None and self.n1 >= 30 and self.n2 >= 30:
            sigma_x1subx2 = self.standard_error(self.sigma1, self.sigma2)
            self.Z = (self.mean1 - self.mean2) / sigma_x1subx2
            self.test_stat = self.Z

        elif (self.sigma1 != None or self.sigma2 != None) or (self.n1 < 30 or self.n2 < 30):
            sigma_x1subx2 = self.standard_error(self.s1, self.s2)
            self.t = (self.mean1 - self.mean2) / sigma_x1subx2
            self.test_stat = self.t

        self.sigma_x1subx2 = sigma_x1subx2

    def get_Z(self):
        print(self.Z)

    def get_t(self):
        print(self.t)

class WilcoxonRankSum(DiffOfMeans):
    """ Compares two independent random sample rank sums for difference
    using Wilcoxon rank sum "W" test.

    Requirements
    ------------
    1. Two independent random samples.
    2. Both population distributions have the same shape (but not
       necessarily normal).
    3. Variable is measured at ordinal or downgraded from interval/raio
       scale to ordinal.

    Null Hypthothesis
    -----------------
    Distribution of measurements for the first population is equal to
    that of the second population.

    Test Statistic
    --------------

        Z_w = SumOfRanksSample_i - MeanRankOfW_i / StandardDeviationOfW

        where

        MeanRankOfW_i = SampleSize_i * ([SampleSize1 + SampleSize2 + 1] / 2)

        and

        StandardDeviationOfW = sqrt( SampleSize1 * SampleSize2 *
                                    {[SampleSize1 + SampleSize2 + 1] / 12} )

        "W" is the Zw of the group with the *smaller* sample size.

    """
    def __init__(self, n1, n2, W1, W2):
        DiffOfMeans.__init__(self, n1, n2)
        """
        Parameters
        ----------
        W1 : float
            The sum of ranks for sample 1.
        W2 : float
            The sum of ranks for sample 2.
        """
        self.W1 = W1
        self.W2 = W2
        self.Zw = None
        self.s_w = self.standard_deviation()
        self.test_statistic()
        self.test_stat = self.Zw

    def standard_deviation(self):
        s_w = np.sqrt( self.n1 * self.n2 * (self.n1 + self.n2 + 1) / 12.0 )
        return s_w

    def mean_rank_W(self, n):
        mean_rank_W = n * (self.n1 + self.n2 + 1) / 2.0
        return mean_rank_W

    def test_statistic(self):
        # Calculate for the sample with smaller size.
        if self.n1 < self.n2:
            self.Zw = (self.W1 - self.mean_rank_W(self.n1)) / self.s_w
        else:
            self.Zw = (self.W2 - self.mean_rank_W(self.n2)) / self.s_w

    def get_Zw(self):
        print(self.Zw)

class DiffOfProportions():
    """ Compares two independent random sample proportions for difference.

    Requirements
    ------------
    1. Two independent random samples.
    2. Variable is organized by dichotomous (binary) categories.

    Null Hypthothesis
    -----------------
    Proportion1 = Proportion2

    Test Statistic
    --------------

        Z_p = (SampleProportion1 - SampleProportion2) / StandErrorDifferenceOfProportions

        where

        StandErrorDifferenceOfProportions = sqrt( PooledEstimate * (1 - PooledEstimate ) *
                                                 ( [SampleSize1 + SampleSize1]
                                                   / SampleSize1 * SampleSize2 ) )

        where

        PooledEstimate = (SampleSize1 * SampleProportion1 + SampleSize2 * SampleProportion2) /
                         (SampleSize1 + SampleSize2)
    """
    def __init__(self, n1, n2, p1, p2):
        """
        Parameters
        ----------
        n1 : int
            Size of sample 1.
        n2 : int
            Size of sample 2.
        p1 : int
            Proportion of sample 1 in category of focus.
        p2 : int
            Proportion of sample 2 in category of focus.
        """
        self.n1 = float(n1)
        self.n2 = float(n2)
        self.p1 = p1
        self.p2 = p2
        self.pooled_estimate = None
        self.Zp = None
        self.sigma_p1subp2 = self.standard_error()
        self.test_statistic()
        self.test_stat = self.Zp

    def standard_error(self):
        """ Calculates standard error of difference of proportions.
        """
        # The weighted proportion of the two samples.
        pooled_estimate = (self.n1 * self.p1 + self.n2 * self.p2) / (self.n1 + self.n2)
        sigma_p1subp2 = np.sqrt( pooled_estimate * (1 - pooled_estimate) * \
                                 ((self.n1 + self.n2) / (self.n1 * self.n2)) )
        self.pooled_estimate = pooled_estimate
        return sigma_p1subp2

    def test_statistic(self):
        self.Zp = abs(self.p1 - self.p2) / self.sigma_p1subp2

    def get_Zp(self):
        print(self.Zp)


import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import truncexpon
from scipy.stats import norm

def f_rvs(num_rvs):
    return norm.rvs(size=num_rvs)

def f(x):
    return norm.pdf(x)

def g_rvs(num_rvs, limit=4.5):
    return truncexpon.rvs(loc=limit, b=np.inf, size=num_rvs)

def g(x, limit=4.5):
    return truncexpon.pdf(x, loc=limit, b=np.inf)

def h(x, limit=4.5):
    return np.where(x > limit, 1.0, 0.0)

def I_1(rvs, limit=4.5):
    return np.mean(h(rvs, limit))

def I_2(rvs, limit=4.5):
    return np.mean(h(rvs, limit) * f(rvs) / g(rvs, limit))

N = 10000
cut_off = 4.5

norm_rvs = f_rvs(N)
result_1 = I_1(norm_rvs, cut_off)

expon_rvs = g_rvs(N, cut_off)
result_2 = I_2(expon_rvs, cut_off)

result_true = 1.0 - norm.cdf(cut_off)

print('Monte Carlo integration result = {:.5f}'.format(result_1))
print('Importance sampling integration result = {:.5f}'.format(result_2))
print('True result = {:.5f}'.format(result_true))
print(80 * '-')
print('Monte Carlo integration error = {:.5f}'.format(
    np.abs(result_1-result_true)))
print('Importance sampling integration error = {:.5f}'.format(
    np.abs(result_2-result_true)))

plt.hist(norm_rvs, bins=100,
         label='$Yi$ from standard normal distribution',
         alpha=0.5, density=True)
plt.hist(expon_rvs, bins=100,
         label='$X_i$ from exponential distribution truncated at {}'.format(
             cut_off),
         alpha=0.5, density=True)
plt.plot(np.linspace(-5, 5, 10000), norm.pdf(np.linspace(-5, 5, 10000)),
         label='Standard normal pdf')
plt.legend()
plt.show()


import math as math
import numpy as np
from numba import njit
from config import MAX_HEIGHT_3D, MAX_WIDTH_3D, MIN_WIDTH_3D, MIN_HEIGHT_3D, CELL_SIZE
from shared import convert_to_list_of_tuples, convert_to_list_of_arrays

def get_line_equations(corners):
    point_a = corners[0]
    point_b = corners[3]
    line_ab = point_a[0] - point_b[0], point_b[1] - point_a[1], point_a[1] * point_b[0] - point_b[1] * point_a[0]
    point_c = corners[1]
    point_d = corners[2]
    line_cd = point_c[0] - point_d[0], point_d[1] - point_c[1], point_c[1] * point_d[0] - point_d[1] * point_c[0]
    return line_ab, line_cd

def get_vanishing_point(corners):
    line_ab, line_cd = get_line_equations(corners)
    # cv2.line(img, tuple([int(-line_ab[2] / line_ab[1]), 0]), tuple([0, int(-line_ab[2] / line_ab[0])]), (0, 255,
    # 0), 2)
    # cv2.line(img, tuple([int(-line_cd[2] / line_cd[1]), 0]), tuple([0, int(-line_cd[2] / line_cd[0])]), (0,
    # 255, 0), 2)
    print("line_ab: ", line_ab[0], " * x +", line_ab[1], " * y + (", line_ab[2], ")")
    print("line_cd: ", line_cd[0], " * x +", line_cd[1], " * y + (", line_cd[2], ")")
    determinant = line_ab[0] * line_cd[1] - line_cd[0] * line_ab[1]
    if determinant == 0:
        return False
    else:
        x = (line_ab[1] * line_cd[2] - line_cd[1] * line_ab[2]) / determinant
        y = (line_cd[0] * line_ab[2] - line_ab[0] * line_cd[2]) / determinant
        print("vanishing point:", (x, y))
        return y, x

def get_focal_length(img):
    height, width = img.shape[0], img.shape[1]
    d = math.sqrt(math.pow(width, 2) + math.pow(height, 2))
    cot = 1 / math.tan(np.deg2rad(39))
    return d / 2 * cot

def get_projected_paper_width(img, corners):
    height, width = img.shape[0], img.shape[1]
    line_ab, line_cd = get_line_equations(corners)
    first_x = -(line_ab[0] * height + line_ab[2]) / line_ab[1]
    second_x = -(line_cd[0] * height + line_cd[2]) / line_cd[1]
    first_x = -(line_ab[1] * height + line_ab[2]) / line_ab[0]
    second_x = -(line_cd[1] * height + line_cd[2]) / line_cd[0]
    return second_x - first_x

def get_pitch_angle(height, row, focal_length):
    aux = (height / 2 - row) / focal_length
    return np.rad2deg(np.arctan(aux))

def get_yaw_angle(width, col, focal_length):
    aux = (width / 2 - col) / focal_length
    return np.rad2deg(np.arctan(aux))

def get_vertical_half_field_of_view(height, focal_length):
    aux = (height / 2) / focal_length
    return np.rad2deg(np.arctan(aux))

def compute_projection_matrix(img, corners):
    height, width = img.shape[0], img.shape[1]
    vanishing_point = get_vanishing_point(corners)
    focal_length = get_focal_length(img)
    pitch = get_pitch_angle(height, vanishing_point[1], focal_length)
    vertical_half_field_of_view = get_vertical_half_field_of_view(height, focal_length)
    w = get_projected_paper_width(img, corners)
    d = math.sqrt(math.pow(focal_length, 2) + pow(height / 2, 2))
    D = (d * 300) / w
    sigma = 90 - vertical_half_field_of_view - pitch
    h = D * math.cos(np.deg2rad(sigma))
    yaw = get_yaw_angle(width, vanishing_point[0], focal_length)

    A = np.float32([[focal_length, 0, width / 2],
                    [0, focal_length, height / 2],
                    [0, 0, 1]])
    Rx = np.float32([[1, 0, 0],
                     [0, np.cos(np.deg2rad(pitch)), -np.sin(np.deg2rad(pitch))],
                     [0, np.sin(np.deg2rad(pitch)), np.cos(np.deg2rad(pitch))]])
    Ry = np.float32([[np.cos(np.deg2rad(yaw)), 0, np.sin(np.deg2rad(yaw))],
                     [0, 1, 0],
                     [-np.sin(np.deg2rad(yaw)), 0, np.cos(np.deg2rad(yaw))]])
    R = np.matmul(Rx, Ry)
    Tcw = np.float32([[0], [-h], [0]])
    Twc = -1 * np.matmul(R, Tcw)
    X = np.concatenate((R, Twc), axis=1)
    P = np.matmul(A, X)
    print("image width =", width, "| image height =", height)
    print("focal length = ", focal_length)
    print("pitch = ", pitch)
    print("yaw = ", yaw)
    print("vertical half field of view = ", vertical_half_field_of_view)
    print("w = ", w)
    print("d = ", d)
    print("D = ", D)
    print("h = ", h)
    print(P)
    return P

def compute_ipm_slow(img, P, corners):
    height, width = img.shape[0], img.shape[1]
    width_3D = MAX_WIDTH_3D - MIN_WIDTH_3D
    height_3D = MAX_HEIGHT_3D - MIN_HEIGHT_3D
    IPM_width = int(width_3D / CELL_SIZE)
    IPM_height = int(height_3D / CELL_SIZE)
    result = np.zeros((IPM_height, IPM_width, 3), np.uint8)
    d = {}
    for corner in corners:
        d[corner] = []
    print(IPM_height * IPM_width)
    for y in range(0, IPM_height):
        for x in range(0, IPM_width):
            x_3D = (x - IPM_width / 2) * CELL_SIZE
            z_3D = MIN_HEIGHT_3D + y * CELL_SIZE
            point_3D = np.float32([
                [x_3D],
                [0],
                [z_3D],
                [1]
            ])
            point_IPM = np.matmul(P, point_3D)
            if point_IPM[2] != 0:
                x_new = int(np.round(point_IPM[0] / point_IPM[2]))
                y_new = int(np.round(point_IPM[1] / point_IPM[2]))
                if 0 <= x_new < width and 0 <= y_new < height:
                    result[y][x] = img[y_new][x_new]
                    for corner in corners:
                        if corner[1] - 3 <= y_new <= corner[1] + 3 and corner[0] - 3 <= x_new <= corner[0] + 3:
                            d[corner].append((x_new, y_new, x, y))
    ipm_corners = []
    for corner in d:
        min_dist = math.inf
        best_candidate = (-1, -1, -1, -1)
        candidates = d[corner]
        for candidate in candidates:
            dist = np.sqrt(np.power(corner[0] - candidate[0], 2) + np.power(corner[1] - candidate[1], 2))
            if dist < min_dist:
                min_dist = dist
                best_candidate = candidate
        ipm_corners.append((best_candidate[2], best_candidate[3]))
    print(ipm_corners)
    return result, ipm_corners

@njit(['Tuple((uint8[:,:,:], int32[:,:]))(uint8[:,:,:], float32[:,:], int32[:,:])'])
def compute_ipm_fast_numba(img, P, corners):
    height, width = img.shape[0], img.shape[1]
    width_3D = MAX_WIDTH_3D - MIN_WIDTH_3D
    height_3D = MAX_HEIGHT_3D - MIN_HEIGHT_3D
    IPM_width = int(width_3D / CELL_SIZE)
    IPM_height = int(height_3D / CELL_SIZE)
    result = np.zeros((IPM_height, IPM_width, 3), np.uint8)
    candidates = np.zeros((4, 2000), np.int32)
    indices = np.zeros(4, np.int32)
    for y in range(0, IPM_height):
        for x in range(0, IPM_width):
            x_3D = (x - IPM_width / 2) * CELL_SIZE
            z_3D = MIN_HEIGHT_3D + y * CELL_SIZE
            point_3D = np.zeros((4, 1), dtype=np.float32)
            point_3D[0][0] = x_3D
            point_3D[1][0] = 0
            point_3D[2][0] = z_3D
            point_3D[3][0] = 1
            point_IPM = P @ point_3D
            if point_IPM[2][0] != 0:
                x_temp = point_IPM[0][0] / point_IPM[2][0]
                y_temp = point_IPM[1][0] / point_IPM[2][0]
                x_new = np.int(np.round(x_temp))
                y_new = np.int(np.round(y_temp))
                if 0 <= x_new < width and 0 <= y_new < height:

                    # Bilinear Interpolation
                    x_0 = np.int(np.floor(x_temp))
                    x_1 = x_0 + 1
                    y_0 = np.int(np.floor(y_temp))
                    y_1 = y_0 + 1
                    if x_1 < width and y_1 < height:
                        f_Q00 = img[y_0][x_0]
                        f_Q01 = img[y_0][x_1]
                        f_Q10 = img[y_1][x_0]
                        f_Q11 = img[y_1][x_1]
                        f_x_y0 = (x_1 - x_temp) * f_Q00 + (x_temp - x_0) * f_Q01
                        f_x_y1 = (x_1 - x_temp) * f_Q10 + (x_temp - x_0) * f_Q11
                        result[y][x] = (y_1 - y_temp) * f_x_y0 + (y_temp - y_0) * f_x_y1

                    # Neirest Neighbour Interpolation
                    # result[y][x] = img[y_new][x_new]

                    for a in range(0, len(corners)):
                        corner = corners[a]
                        if corner[1] - 3 <= y_new <= corner[1] + 3 and corner[0] - 3 <= x_new <= corner[0] + 3:
                            i = indices[a]
                            candidates[a][i] = x_new
                            i += 1
                            candidates[a][i] = y_new
                            i += 1
                            candidates[a][i] = x
                            i += 1
                            candidates[a][i] = y
                            i += 1
                            indices[a] = i
    ipm_corners = np.zeros((4, 2), np.int32)
    best_candidate = np.zeros(4, np.int32)
    for a in range(0, len(corners)):
        corner = corners[a]
        min_dist = math.inf
        best_candidate[0] = -1
        best_candidate[1] = -1
        best_candidate[2] = -1
        best_candidate[3] = -1
        for i in range(0, candidates.shape[1], 4):
            if candidates[a][i] != 0:
                dist = np.sqrt(
                    np.power(corner[0] - candidates[a][i], 2) + np.power(corner[1] - candidates[a][i + 1], 2))
                if dist < min_dist:
                    min_dist = dist
                    best_candidate[0] = candidates[a][i]
                    best_candidate[1] = candidates[a][i + 1]
                    best_candidate[2] = candidates[a][i + 2]
                    best_candidate[3] = candidates[a][i + 3]
        ipm_corners[a][0] = best_candidate[2]
        ipm_corners[a][1] = best_candidate[3]
    return result, ipm_corners

def compute_ipm_and_corners(projection_matrix, img, current_image_corners):
    current_image_corners_as_arrays = convert_to_list_of_arrays(current_image_corners)
    ipm_image, current_ipm_corners_as_arrays = \
        compute_ipm_fast_numba(img, projection_matrix, np.asarray(current_image_corners_as_arrays))
    current_ipm_corners = convert_to_list_of_tuples(current_ipm_corners_as_arrays)
    current_ipm_corners.reverse()
    return ipm_image, current_ipm_corners

def convert_from_image_corners_to_ipm_corners(P, image_corners):
    width_3D = MAX_WIDTH_3D - MIN_WIDTH_3D
    IPM_width = int(width_3D / CELL_SIZE)
    ipm_corners = []
    for corner in image_corners:
        x, y = corner
        A = np.array([[P[0][0] - x * P[2][0], P[0][2] - x * P[2][2]],
                      [P[1][0] - y * P[2][0], P[1][2] - y * P[2][2]]])
        B = np.array([[x * P[2][3] - P[0][3]],
                      [y * P[2][3] - P[1][3]]])
        inv_A = np.linalg.inv(A)
        X = inv_A.dot(B)
        # y_ipm = int(np.round(X[0] / CELL_SIZE + IPM_width / 2))
        # x_ipm = int(np.round((X[1] - MIN_HEIGHT_3D) / CELL_SIZE))
        x_ipm = int(np.round(X[0] / CELL_SIZE + IPM_width / 2))
        y_ipm = int(np.round((X[1] - MIN_HEIGHT_3D) / CELL_SIZE))
        ipm_corners.append((x_ipm, y_ipm))
    ipm_corners.reverse()
    return ipm_corners

def convert_from_ipm_corners_to_image_corners(img, P, ipm_corners):
    height, width = img.shape[0], img.shape[1]
    width_3D = MAX_WIDTH_3D - MIN_WIDTH_3D
    IPM_width = int(width_3D / CELL_SIZE)
    img_corners = []
    for corner in ipm_corners:
        y = corner[1]
        x = corner[0]
        x_3D = (x - IPM_width / 2) * CELL_SIZE
        z_3D = MIN_HEIGHT_3D + y * CELL_SIZE
        point_3D = np.float32([
            [x_3D],
            [0],
            [z_3D],
            [1]
        ])
        point_IPM = np.matmul(P, point_3D)
        if point_IPM[2] != 0:
            x_new = int(np.round(point_IPM[0] / point_IPM[2]))
            y_new = int(np.round(point_IPM[1] / point_IPM[2]))
            if 0 <= x_new < width and 0 <= y_new < height:
                img_corners.append((x_new, y_new))
    img_corners.reverse()
    return img_corners


import numpy as np
import matplotlib.pyplot as plt
from scipy.stats import norm
import sys

class Gaussian_Process_Regression():
    def __init__(self):
        self.K = None
        self.kernel_name1 = 'RBF'
        self.a1_1 = 200.0
        self.a2_1 = 20.0
        self.a3_1 = 0.0

    def xx2K(self,xn,xm):
        if (len(xn) == 1):
            self.K = np.zeros([1,len(xm)])
        else :
            self.K = 0.0*np.outer(xn,xm)
        for i in range(len(xn)):
            self.K[i,:] = self.a1_1*np.exp(-(xn[i] - xm[:])**2/self.a2_1) + self.a3_1
        return self.K

    def xsample2meanvariance(self,_xsample, _ysample, _x, eps = 1.0e-8):
        self.K = self.xx2K(_xsample,_xsample) + eps*np.eye(len(_xsample))
        L = np.linalg.cholesky(self.K)
        #plt.matshow(K)
        #plt.matshow(L)
        kast = self.xx2K(_xsample,_x)
        kastast = self.xx2K(_x,_x)
        w = np.linalg.solve(L, _ysample)
        z = np.linalg.solve(L.T, w)
        mean = np.dot(kast.T, z)
        W = np.linalg.solve(L, kast)
        Z = np.linalg.solve(L.T, W)
        fvariance = kastast - np.dot(kast.T, Z)
        fvariance = np.diag(fvariance)
        std = np.sqrt(fvariance)
        return mean, std

class  Bayesian_opt():
    def __init__(self):
        self.aqui_name = 'PI' #'PI', 'EI', 'UCB'
        self.xi = 0.01

#### PI
    def aqui_PI(self, mean, std, maxval):
        Z = (mean -  maxval - self.xi)/std
        return norm.cdf(Z)
#### EI
    def aqui_EI(self, mean, std, maxval):
        Z = (mean -  maxval - self.xi)/std
        return (mean - maxval - self.xi)*norm.cdf(Z) + std*norm.pdf(Z)
#### UCB
    def aqui_UCB(self, mean, std, maxval):
        return mean + 1.0*std

    def get_aqui(self, mean, std, maxval):
        if (self.aqui_name == 'PI'):
            aqui = self.aqui_PI(mean, std, maxval)
        elif (self.aqui_name == 'EI'):
            aqui = self.aqui_EI(mean, std, maxval)
        elif (self.aqui_name == 'UCB'):
            aqui = self.aqui_UCB(mean, std, maxval)
        else:
            print('# ERROR: undefined acquisition function called.')
            sys.exit()

        return aqui


#! -*- coding:utf-8 -*-
# 学习python 矩阵运算
# 实际应用是矩阵位置变换
import numpy as np

# G1原始坐标矩阵
G1 = np.array([[0,1,0,2],[1,0,0,6],[0,0,-1,2],[0,0,0,1]])
G1 = np.mat(G1)

# 旋转弧度
a1 = np.pi/2

# Z轴旋转矩阵T1
T1 = np.array([[np.cos(a1),-np.sin(a1),0,0],[np.sin(a1),np.cos(a1),0,0],[0,0,1,0],[0,0,0,1]])
T1 = np.mat(T1)

#算子左乘：表示点的平移是相对固定坐标系进行的坐标变换。
G2 = T1*G1
#算子右乘：表示点的平移是相对动坐标系进行的坐标变换。
G3 = G1*T1

print(G1,'\n\n',T1,'\n\n',G2,'\n\n',G3,'\n\n')

# 已知坐标系中点U的位置矢量 u=[7 3 2 1]T，将此点绕Z轴旋转90°，再绕Y轴旋转90°，求旋转后所得点W
# w = Rot(Y,90°)*Rot(Z,90°)*u

U = np.array([[7],[3],[2],[1]])
U = np.mat(U)

T2 = np.array([[np.cos(a1),0,np.sin(a1),0],[0,1,0,0],[-np.sin(a1),0,np.cos(a1),0],[0,0,0,1]])
T2 = np.mat(T2)
print('T2=',T2,'\n\n')

T4 = np.array([[0,0,1,0],[0,1,0,0],[-1,0,0,0],[0,0,0,1]])
T4 = np.mat(T4)

T3 = np.array([[0,-1,0,0],[1,0,0,0],[0,0,1,0],[0,0,0,1]])
T3 = np.mat(T3)

W = T2*T1*U
W2 = T4*T3*U
print('W=',W,'\n\n\n')
print('W2= ',W2,'\n\n\n')


import math
from typing import NoReturn
from ...base import BaseEstimator
import numpy as np
from numpy.linalg import det, inv

class GaussianNaiveBayes(BaseEstimator):
    """
    Gaussian Naive-Bayes classifier
    """
    def __init__(self):
        """
        Instantiate a Gaussian Naive Bayes classifier

        Attributes
        ----------
        self.classes_ : np.ndarray of shape (n_classes,)
            The different labels classes. To be set in `GaussianNaiveBayes.fit`

        self.mu_ : np.ndarray of shape (n_classes,n_features)
            The estimated features means for each class. To be set in `GaussianNaiveBayes.fit`

        self.vars_ : np.ndarray of shape (n_classes, n_features)
            The estimated features variances for each class. To be set in `GaussianNaiveBayes.fit`

        self.pi_: np.ndarray of shape (n_classes)
            The estimated class probabilities. To be set in `GaussianNaiveBayes.fit`
        """
        super().__init__()
        self.classes_, self.mu_, self.vars_, self.pi_ = None, None, None, None

    def _fit(self, X: np.ndarray, y: np.ndarray) -> NoReturn:
        """
        fits a gaussian naive bayes model

        Parameters
        ----------
        X : ndarray of shape (n_samples, n_features)
            Input data to fit an estimator for

        y : ndarray of shape (n_samples, )
            Responses of input data to fit to
        """
        self.classes_, classes_occurrences = np.unique(y, return_counts=True)
        k = len(self.classes_)
        m, d = X.shape
        self.vars_ = np.zeros((k, d))
        self.mu_ = np.zeros((k, d))
        self.pi_ = classes_occurrences / m
        for i in range(k):
            self.mu_[i] = np.mean(X[np.where(y == i)], axis=0)
            self.vars_[i] = np.var(X[y == i], axis=0)
        self.fitted_ = True

    def _predict(self, X: np.ndarray) -> np.ndarray:
        """
        Predict responses for given samples using fitted estimator

        Parameters
        ----------
        X : ndarray of shape (n_samples, n_features)
            Input data to predict responses for

        Returns
        -------
        responses : ndarray of shape (n_samples, )
            Predicted responses of given samples
        """
        y_pred = np.argmax(self.likelihood(X), axis=1)
        return np.array(y_pred)

    def likelihood(self, X: np.ndarray) -> np.ndarray:
        """
        Calculate the likelihood of a given data over the estimated model

        Parameters
        ----------
        X : np.ndarray of shape (n_samples, n_features)
            Input data to calculate its likelihood over the different classes.

        Returns
        -------
        likelihoods : np.ndarray of shape (n_samples, n_classes)
            The likelihood for each sample under each of the classes

        """
        if not self.fitted_:
            raise ValueError("Estimator must first be fitted before calling `likelihood` function")

        likelihood = []
        k = len(self.classes_)
        d = X.shape[1]
        for i in range(k):
            Z = (math.sqrt(math.pow(2 * math.pi, d) * det(np.diag(self.vars_[i]))))
            x_minus_mu_mat = X - self.mu_[i]
            mat_mul = np.exp(np.diag(-0.5 * x_minus_mu_mat @  inv(np.diag(self.vars_[i])) @ x_minus_mu_mat.T))
            likelihood.append(self.pi_[i]*mat_mul / Z)
        return np.array(likelihood).T

    def _loss(self, X: np.ndarray, y: np.ndarray) -> float:
        """
        Evaluate performance under misclassification loss function

        Parameters
        ----------
        X : ndarray of shape (n_samples, n_features)
            Test samples

        y : ndarray of shape (n_samples, )
            True labels of test samples

        Returns
        -------
        loss : float
            Performance under missclassification loss function
        """
        from ...metrics import misclassification_error
        y_pred = self.predict(X)
        return misclassification_error(y, y_pred)


"""
This python code demonstrates an edge-based active contour model as an application of the
Distance Regularized Level Set Evolution (DRLSE) formulation in the following paper:

  C. Li, C. Xu, C. Gui, M. D. Fox, "Distance Regularized Level Set Evolution and Its Application to Image Segmentation",
     IEEE Trans. Image Processing, vol. 19 (12), pp. 3243-3254, 2010.

Author: Ramesh Pramuditha Rathnayake
E-mail: rsoft.ramesh@gmail.com

Released Under MIT License
"""

import numpy as np
from skimage.io import imread

from lv_set.find_lsf import find_lsf
from lv_set.potential_func import *
from lv_set.show_fig import draw_all

def gourd_params():
    img = imread('gourd.bmp', True)
    img = np.interp(img, [np.min(img), np.max(img)], [0, 255])

    # initialize LSF as binary step function
    c0 = 2
    initial_lsf = c0 * np.ones(img.shape)
    # generate the initial region R0 as two rectangles
    initial_lsf[24:35, 19:25] = -c0
    initial_lsf[24:35, 39:50] = -c0

    # parameters
    return {
        'img': img,
        'initial_lsf': initial_lsf,
        'timestep': 1,  # time step
        'iter_inner': 10,
        'iter_outer': 30,
        'lmda': 5,  # coefficient of the weighted length term L(phi)
        'alfa': -3,  # coefficient of the weighted area term A(phi)
        'epsilon': 1.5,  # parameter that specifies the width of the DiracDelta function
        'sigma': 0.8,  # scale parameter in Gaussian kernel
        'potential_function': DOUBLE_WELL,
    }

def two_cells_params():
    img = imread('twocells.bmp', True)
    img = np.interp(img, [np.min(img), np.max(img)], [0, 255])

    # initialize LSF as binary step function
    c0 = 2
    initial_lsf = c0 * np.ones(img.shape)
    # generate the initial region R0 as two rectangles
    initial_lsf[9:55, 9:75] = -c0

    # parameters
    return {
        'img': img,
        'initial_lsf': initial_lsf,
        'timestep': 5,  # time step
        'iter_inner': 5,
        'iter_outer': 40,
        'lmda': 5,  # coefficient of the weighted length term L(phi)
        'alfa': 1.5,  # coefficient of the weighted area term A(phi)
        'epsilon': 1.5,  # parameter that specifies the width of the DiracDelta function
        'sigma': 1.5,  # scale parameter in Gaussian kernel
        'potential_function': DOUBLE_WELL,
    }

params = gourd_params()
# params = two_cells_params()
phi = find_lsf(**params)

print('Show final output')
draw_all(phi, params['img'], 10)


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

iris = pd.read_csv("iris.csv")

iris_setosa = iris.loc[iris["species"] == "setosa"];
iris_virginica = iris.loc[iris["species"] == "virginica"];
iris_versicolor = iris.loc[iris["species"] == "versicolor"];

# mean, variance and std-dev gets corrupted by outliers
# so median comes into picture

#Median (similar to mean but doesn't corrupted from outlier)
np.median(iris_setosa["petal_length"])
# 1.5

#Median with an outlier
np.median(np.append(iris_setosa["petal_length"],50))
# 1.5

np.median(iris_virginica["petal_length"])
# 5.55

np.median(iris_versicolor["petal_length"])
# 4.35

# how to find median ?
# sort in ascending order and pick middle value
# when order is even, take middle two values and compute mean

# why median is not corrupted by outliers ?
# when sorted, outlier lye at end

# what happens when half of the values are outlier ?
# when more than 50% of the values are outliers, only then median gets corrupted

# Percentiles & Quantiles --> 25th, 50th, 75th, 100th percentile are called quantiles
# 1st quantile is 25th percentile
# 3rd quantile is 75th percentile
np.percentile(iris_setosa["petal_length"],np.arange(0, 100, 25))
# array([1.   , 1.4  , 1.5  , 1.575])

np.percentile(iris_virginica["petal_length"],np.arange(0, 100, 25))
# array([4.5  , 5.1  , 5.55 , 5.875])

np.percentile(iris_versicolor["petal_length"], np.arange(0, 100, 25))
# array([3.  , 4.  , 4.35, 4.6 ])

np.percentile(iris_setosa["petal_length"],90)
# 1.7

np.percentile(iris_virginica["petal_length"],90)
# 6.3100000000000005

np.percentile(iris_versicolor["petal_length"], 90)
# 4.8

# Ex: why 99 percentile is usefull ?
# 99th percentile = 5.6 days i,e 99 % of customer got delivery of package in 5.6 days --> good

# mean absolute deviation --> how far away are the points from central tendency median. equivalent to std-dev
from statsmodels import robust
robust.mad(iris_setosa["petal_length"])
# 0.14826022185056031

robust.mad(iris_virginica["petal_length"])
# 0.6671709983275211

robust.mad(iris_versicolor["petal_length"])
# 0.5189107764769602

# Inter-quartile range
# 75th percentile - 25th percentile i,e 50 % of values lyes


# -*- coding: utf-8 -*-
"""
=== FIL_Halfband_design.py ================================================

 Generate coefficients for a halfband filter.  A halfband filter
 is a filter where the cutoff frequency is Fs/4 and every
 other coeffecient is zero except for the center tap.
 Due to numeric inaccuracies, coefficients are not exactly zero and are set
 to 0 when below a certain threshold.

 (c) 2016 Christian Münker & Florian Thevissen - Files zur Vorlesung "DSV auf FPGAs"
===========================================================================
"""
from __future__ import division, print_function, unicode_literals

import numpy as np
from numpy import pi, arange, log10
import scipy.signal as sig

import matplotlib.pyplot as plt

N = 16 # Filter order - must be even for Halfband filter!

# --- Filter Design with Parks-McClellan (Remez) method -----------------------
# Filter symmetric around 0.25 (for remez .5 is pi or F = Fs/2 -)
bands = np.array([0., .22, .28, .5]) # define HALFBAND passband / stopband
#bands = np.array([0., .1, .15, .5]) # define passband / stopband
b_rem = sig.remez(N+1, bands, [1, 0], [1, 1], Hz = 1.0)
b_rem[abs(b_rem) <= 1e-4] = 0 # set very small coefficients = 0 (rounding errors)
# normalize for [H(f=0) + |H(f = fS/2)|] = 1
b_rem = b_rem / (sum(b_rem) + abs(np.polyval(b_rem, -1)))
(w, H_rem) = sig.freqz(b_rem)

# --- Filter Design with Windowed method --------------------------------------
# set cutoff frequency = f_Nyq/2 = f_S/4
b_win = sig.firwin(N+1, 0.5, nyq = 1.0) # HALFBAND filter
#b_win = sig.firwin(N+1, 0.25, nyq = 1.0)
b_win[abs(b_win) <= 1e-5] = 0
# normalize for [H(f=0) + |H(f = fS/2)|] = 1
b_win = b_win / (sum(b_win) + abs(np.polyval(b_win, -1)))
(w, H_win) = sig.freqz(b_win)

# --- Filter Design with Least Square method ----------------------------------
#b_ls = sig.firwin(N+1, 0.5, window = 'boxcar')
b_ls = sig.firwin(N+1, 0.5, window = 'boxcar') #Halfband
#b_ls = sig.firwin(N+1, 0.25, width=0.01, window = 'boxcar')

b_ls[abs(b_ls) <= 1e-4] = 0
# normalize for [H(f=0) + |H(f = fS/2)|] = 1
b_ls = b_ls / (sum(b_ls) + abs(np.polyval(b_ls, -1)))
(w, H_ls) = sig.freqz(b_ls)

F = w / (2 * pi)

b_rem_0 = []
b_win_0 = []
b_ls_0 = []

# Print coefficients for comparison and verification & find zero coefficients
print('          remez      firwin     Least-Square')
print('--------------------------------------------')
for i in range(N+1):
    print(' tap %2d  %+3.6F  %+3.6f  %+3.6f' %(i, b_rem[i], b_win[i], b_ls[i]))
    if b_rem[i] == 0: b_rem_0.append(i)
    if b_win[i] == 0: b_win_0.append(i)
    if b_ls[i] == 0: b_ls_0.append(i)

#--------------------- Plot impulse responses of filters ----------------------
fig1 = plt.figure(1)
ax11 = fig1.add_subplot(311)
ax11.stem(arange(len(b_ls)), b_ls, label = 'LeastSquare') # impulse response
ax11.scatter(b_ls_0, np.zeros(len(b_ls_0)), s = 300, facecolors=(0.5,1,0.5,0.7),
             edgecolors='darkgreen') # mark zero coefficients
ax11.grid(True)
ax11.legend()
ax11.set_xlim(0, N)
ax11.set_title('Impulse Response')

ax12 = fig1.add_subplot(312)
ax12.stem(arange(len(b_win)), b_win, label = 'Windowed LS')
ax12.scatter(b_win_0, np.zeros(len(b_win_0)), s = 300,
             facecolors=(0.5,1,0.5,0.7), edgecolors='darkgreen')

ax12.plot(np.arange(N+1), np.max(b_win) * sig.windows.hamming(N+1), '--')
ax12.grid(True)
ax12.legend()
ax12.set_xlim(0, N)

ax13 = fig1.add_subplot(313)
ax13.stem(arange(len(b_rem)), b_rem, label = 'Remez')
ax13.scatter(b_rem_0, np.zeros(len(b_rem_0)), s = 300,
             facecolors=(0.5,1,0.5,0.7), edgecolors='darkgreen')
ax13.grid(True)
ax13.legend()
ax13.set_xlim(0, N)
plt.tight_layout()

#--------------------- Plot linear amplitude response -------------------------
fig2 = plt.figure(2)
ax21 = fig2.add_subplot(111)
ax21.plot(F, abs(H_ls), label = 'LeastSquare')
ax21.plot(F, abs(H_win), label = 'Windowed LS')
ax21.plot(F, abs(H_rem), label = 'Remez')
ax21.legend()
ax21.axvspan(bands[1], bands[2], facecolor='0.8')# transition band in grey
ax21.plot(1/4, 1/2, 'o', markerfacecolor=(0.5,1,0.5,0.7), markersize = 15,
          markeredgecolor = 'darkgreen')# mark the symmetry point
ax21.axvline(1/4, color='g', linestyle='--')
ax21.axis([0,1/2,0,1.2])
ax21.grid('on')
ax21.set_ylabel('Magnitude')
ax21.set_xlabel('Normalized Frequency')
ax21.set_title('Linear Filter Frequency Response')

#--------------------- Plot log. amplitude response ---------------------------
fig3 = plt.figure(3)
ax31 = fig3.add_subplot(111)
ax31.plot(F, 20*log10(abs(H_ls)), label = 'LeastSquare')
ax31.plot(F, 20*log10(abs(H_win)), label = 'Windowed LS')
ax31.plot(F, 20*log10(abs(H_rem)), label = 'Remez')
ax31.legend()
ax31.axvspan(bands[1], bands[2], facecolor='0.8') # transition band in grey
ax31.plot(1/4, -20*log10(2.), 'o', markerfacecolor=(0.5,1,0.5,0.7),
          markersize = 15, markeredgecolor = 'k')
ax31.axvline(1/4, color='g', linestyle='--')
ax31.axis([0,1/2,-64,3])
ax31.grid('on')
ax31.set_ylabel('Magnitude (dB)')
ax31.set_xlabel('Normalized Frequency')
ax31.set_title('Log. Filter Frequency Response')

plt.show()


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sun Apr 29 21:11:44 2018

@author: tyler
"""

import numpy as np
import matplotlib.pyplot as plt
from scipy import sparse
from scipy.sparse import linalg

#<start>
def heat_CN_FWE(m):
#
# heat_CN.py
#
# Solve u_t = kappa * u_{xx} on [ax,bx] with Dirichlet boundary conditions,
# using the Crank-Nicolson method with m interior points.
#
# Returns k, h, and the max-norm of the error.
# This routine can be embedded in a loop on m to test the accuracy,
# perhaps with calls to error_table and/or error_loglog.
#
# Original MATLAB code from  http://www.amath.washington.edu/~rjl/fdmbook/  (2007)
# Ported to Python by Tyler Chen (2018)

    plt.figure()              # clear graphics
                              # Put all plots on the same graph (comment out if desired)

    ax = 0;
    bx = 1;
    kappa = .02;                 # heat conduction coefficient:
    tfinal = 1;                  # final time

    h = (bx-ax)/(m+1);           # h = delta x
    x = np.linspace(ax,bx,m+2);  # note x(1)=0 and x(m+2)=1
                                 # u(1)=g0 and u(m+2)=g1 are known from BC's
    k = 24*h**2;                 # time step

    nsteps = round(tfinal / k);  # number of time steps

    #nplot = 1;      # plot solution every nplot time steps
                     # (set nplot=2 to plot every 2 time steps, etc.)
    nplot = nsteps;  # only plot at final time

    if abs(k*nsteps - tfinal) > 1e-5:
        # The last step won't go exactly to tfinal.
        print(' ')
        print('WARNING *** k does not divide tfinal, k = %1.5f' % k)
        print(' ')

    # true solution for comparison:
    # For Gaussian initial conditions u(x,0) = exp(-beta * (x-0.4)^2)
    beta = 150;
    utrue = lambda x,t: np.exp(-(x-0.4)**2 / (4*kappa*t + 1/beta)) / np.sqrt(4*beta*kappa*t+1);

    # initial conditions:
    u0 = utrue(x,0);

    # Each time step we solve MOL system U' = AU + g using the TRBDF2

    # set up matrices:
    r = kappa * k/(h**2);
    e = np.ones(m);
    A = sparse.spdiags([e,-2*e,e],[-1,0,1],m,m)
    A1_ = sparse.eye(m) + (r / 4) * A;
    A2_ = sparse.eye(m) - (r / 4) * A;
    A2 = sparse.eye(m) - (r / 3) * A;

    # initial data on fine grid for plotting:
    xfine = np.linspace(ax,bx,1001);
    ufine = utrue(xfine,0);

    # initialize u and plot:
    tn = 0;
    u = u0;

    plt.plot(x,u,'b.-', xfine,ufine,'r')
    plt.legend(['computed','true'])
    plt.title('Initial data at time = 0')

    # main time-stepping loop:
    for n in range(nsteps):
        tnp = tn + k;   # = t_{n+1}
        # boundary values u(0,t) and u(1,t) at times tn and tnp:

        g0n = u[0];
        g1n = u[m+1];
        g0np = utrue(ax,tnp);
        g1np = utrue(bx,tnp);

        # compute right hand side for intermediate linear system:
        uint = u[1:-1];   # interior points (unknowns)
        rhs = r*A @ uint;
        # fix-up right hand side using BC's (i.e. add vector g to A2*uint)
        rhs[0] += r * g0n;
        rhs[m-1] += r * g1n;

        uint += rhs

        # augment with boundary values:
        u = np.concatenate([[g0np], uint, [g1np]]);
        # plot results at desired times:
        if (n+1)%nplot==0 or (n+1)==nsteps:
            print(n)
            ufine = utrue(xfine,tnp);
            plt.plot(x,u,'b.-', xfine,ufine,'r')
            plt.title('t = %1.5f  after %i time steps with %i grid points' % (tnp,n+1,m+2))
            error = max(abs(u-utrue(x,tnp)));
            print('at time t = %.5f  max error =  %.5f'%(tnp,error))
            if (n+1)<nsteps: input('Hit <return> to continue  ')

        tn = tnp;   # for next time step
    plt.show()

    return k,h,error

#<end>


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Tue Oct 29 00:21:29 2019

@author: faisal
"""
# This is an example illustrates the Conjugate gradient optimization method
import numpy as np
import matplotlib.pyplot as plt
# Assume that A in the shape [[2a, b], [b , 2c]]
# for a quadrtic form ax^2 + b xy + b y^2
def Conjugate_gradient(A, b, plot_solution=False):
   Xs = []
   # initial guess
   x = np.random.random(2) * [5,9]
   Xs.append(np.copy(x))
   # compute the initial resdual and choose it as the first direction to optimize
   # accroding to
   r = b - np.dot(A, x)
   d = r
   k = 0
   # optimization loop
   while True:
      alpha = np.dot(d,r) / np.dot(d, np.dot(A,d))
      x += (alpha * d)
      r_new = r - alpha * np.dot(A,d)
      print ('At k = {}, x={}'.format(k,x))
      if np.sqrt(np.dot(r,r)) < 1e-3:
         break
      Xs.append(np.copy(x))
      beta = np.dot(r_new,r_new) / np.dot(r, r)
      d = r_new + beta * d
      k += 1
      r  = r_new
   print(k)
   print(np.dot(A, x))
   if plot_solution:
      plot_func_and_gradient(A, b, Xs)
   return x
# Visulize the function and its solution
def plot_func_and_gradient( A, b, Xs,x_range=[-6,6], y_range=[-6,6], grid_num_points=100, num_countors=30):
   X = np.linspace(x_range[0], x_range[1], grid_num_points)
   Y = np.linspace(y_range[0], y_range[1], grid_num_points)
   for i in range(len(Xs) - 1):
      plt.plot([Xs[i][0],Xs[i+1][0]],[Xs[i][1],Xs[i+1][1]] )
   X, Y= np.meshgrid(X, Y)
   Z = 0.5 * A[0][0] * X**2 + 0.5 * A[1,1] * Y**2 + A[0][1] * X * Y
   plt.contour(X, Y, Z,num_countors)
   plt.show()

if __name__ == '__main__':
   A = np.array([[2/3, 1/5], [1/5, 2/3]])
   b = np.array([0, 0])
   Conjugate_gradient(A, b, True)


# Logistic regression from scratch

import numpy as np
from sklearn.datasets import make_classification
import seaborn as sns
import matplotlib.pyplot as plt

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

def cost_function(X, y, weights):
    z = np.dot(X, weights) # x1w1 + x2w2 ... + xnwn
    # two parts of the cost function
    # if true label is 1 or true label is 0
    predict_1 = y * np.log(sigmoid(z))
    predict_0 = (1-y) * np.log(1 - sigmoid(z))

    # combined and reduce sum of the two eqns
    return -sum(predict_1 + predict_0) / len(X)

def train(X, y, epochs=100, lr = 0.03):
    loss = [] # collection of weights
    weights = np.random.rand(X.shape[1]) # (None, features)
    N = len(X)

    for e in range(epochs):
        y_hat = sigmoid(np.dot(X, weights)) # activation of weighted sum

        # updated weights
        # chain rule to get simplified equ
        # loss function derivative and updated using the gradient update eqn
        weights -= lr * np.dot(X.T, y_hat - y) / N
        s = "ep {}".format(e)
        loss.append({s: cost_function(X, y, weights)})

    return weights, loss

def predict(X, weights):
    z = np.dot(X, weights)
    return [1 if i > 0.5 else 0 for i in sigmoid(z)]

X,y = make_classification(n_samples=2,n_features=4)

weights, loss = train(X, y)
predict(X, weights)


import matplotlib.pyplot as plt
import numpy as np

def LogisticCostFunction(expected, output):
    return -1 * (sum(expected * np.log(output + 0.00000001) + (1 - expected) * np.log(1.00000001 - output)) / len(
        expected))

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

def gradientDescent(alpha):
    input = np.array([[1, 2], [2, 3], [3, 4], [4, 5]])
    params = np.array([[1, 2, 3, 4]])
    expected = np.array([[2], [3]])
    output = np.array([[2], [3]])
    updatedParams = params - alpha * (np.sum(input * (output - expected, 1)))

"""
parameters:
executes the logistic regression for input like
input = np.array([[1, 2], [2, 3], [3, 4], [4, 5]])

params = np.array([[1, 2, 3, 4]])
expected = np.array([[2], [3]])
"""
costarr = []

def logistic_regression(input, params, expected, alpha, epochs):
    for i in range(epochs):
        result = np.dot(params, input)
        result = np.transpose(result)
        result = sigmoid(result)
        cost = LogisticCostFunction(expected, result)
        costarr.append(cost)
        params = params - alpha * (np.sum(input * np.transpose((result - expected)), 1))
    return params

# load the training data
file = open("../data/Social_Network_Ads.csv", "r")
train = np.zeros((0, 4))
out = np.zeros((0, 1))
file.readline()
for line in file.readlines():
    words = line.split(",")
    if words[1] == 'Male':
        train = np.append(train, np.array([[1, 1, float(words[2]), float(words[3])]]), axis=0)
    else:
        train = np.append(train, np.array([[1, 0, float(words[2]), float(words[3])]]), axis=0)
    val = float(words[4][0])
    out = np.append(out, np.array([[val]]), axis=0)
train = np.transpose(train)
# scaling
maxOfRows = np.transpose(np.array([np.max(train, axis=1)]))
minOfRows = np.transpose(np.array([np.min(train, axis=1)]))
trainScaled = train - minOfRows
trainScaled[1:] = trainScaled[1:] / (maxOfRows[1:] - minOfRows[1:])

testScaled, trainScaled = np.hsplit(trainScaled, np.array([40]))
out_test = out[:40]
out_train = out[40:]
params = np.array([[0.01, 0.01, 0.01, 0.01]])
alpha = 0.01
params = logistic_regression(trainScaled, params, out_train, alpha, 50)
plt.plot(np.arange(0, len(costarr)), costarr)
plt.show()
testing_out=sigmoid(np.transpose(np.dot(params, testScaled)))


import numpy as np
from abc import ABC

class CartSphSwitcher(ABC):
    """A spherical <-> Cartesian coordinate switcher."""
    @classmethod
    def cart2sph(cls, x, y, z):
        hxy = np.hypot(x, y)
        r = np.hypot(hxy, z)
        el = np.arctan2(z, hxy)
        az = np.arctan2(y, x)
        return az, el, r

    @classmethod
    def sph2cart(cls, az, el, r):
        r_cos_theta = r * np.cos(el)
        x = r_cos_theta * np.cos(az)
        y = r_cos_theta * np.sin(az)
        z = r * np.sin(el)
        return x, y, z


#!/usr/bin/python
#-*- coding: utf-8 -*-
"""
RSA Demo in Python
author: Jerzy Wawro, Galicea
License:  GNU General Public License <http://www.gnu.org/licenses/>.

pip install primesieve
pip install numpy
"""

import numpy as np
import primesieve
from random import randint

def gen_prime(min, max):
  """
  Eratosthenes sieve http://code.activestate.com/recipes/117119/
  https://github.com/hickford/primesieve-python
  """
  prime_list = primesieve.primes(min, max)
  while (not prime_list):
    min=max
    max+=100
    prime_list = generate_primes(min, max)
  n=randint(0, len(prime_list)-1)
  return prime_list[n]

# The greatest common divisor (GCD) - Euler
def gcd(x, y):
    while y != 0:
        (x, y) = (y, x % y)
    return x

# result == x:  a*x mod n == 1,  0 < a < n
# extended  Euclides
# https://anh.cs.luc.edu/331/notes/xgcd.pdf
def inv(a,n):
  v0 = 0
  v1 = 1
  r0=n
  r1=a
  while r1 != 0:
    d = r0 // r1
    (r0, r1) = r1, r0 - d * r1
    (v0, v1) = v1, v0 - d * v1
  if v0>0:
    return v0
  else:
    return v0+n

def rsa_keys(p, q): # p<q
# return: d, e, p * q
  n=p*q
  fi=(q-1)*(p-1)
  # wybieramy d wzglednie pierwsze wzgledem fi  z przedzialu [q + 1 .. n-1]
  d=q+1
  wd=-1
  while (wd != 1 ) and (d<n):
    wd=gcd(d, fi)
    if wd != 1:
      d+=1
  if wd != 1:
    print('nie znaleziono kluczy')
    exit(-1)
  e = inv(d, fi)
  return (d, e, n)

def rsa(M, d, n):
  return (M ** d) % n

if __name__=="__main__":
  # przykładowe dane startowe
  min=779
  d=88
  # liczby pierwsze
  p=gen_prime(min,min+d)
  q=gen_prime(p,p+d)
  # klucze
  d, e, n = rsa_keys(p, q)
  print ('d=%s, e=%s, n=%s' % (d, e, n))
  # test
  M=input('Liczba=')
  Mcrypt=rsa(M,d,n)
  print("zaszyfrowana=%s" % Mcrypt)
  print("odszyfrowana=%s" %   rsa(Mcrypt,e,n))


# coding: utf-8
# WaveMaker Code
# by kense
# ############
import numpy as np
import matplotlib.pyplot as plt

np.random.seed(seed=None) # random seed

def jonswap(f,Hs,Tp): # JONSWAP function

	fp=1/float(Tp)

	TH = Tp/float(np.sqrt(Hs))

	if TH<=3.6:

			gamma=5

	elif (3.6<TH) and (TH<=5):

			gamma=np.exp(5.75-1.15*TH)

	else:
			gamma=1

	if f<=fp:

    		sigma = 0.07

	else:

    		sigma = 0.09

	s=0.3125*Hs**2*Tp*(f/float(fp))**(-5)*np.exp(-1.25*(f/float(fp))**(-4))*(1-0.287*np.log(gamma))*gamma**(np.exp(-0.5*((f/float(fp)-1)/float(sigma))**2))

	return s

def x0(TDur,dt,Hs,Tp,f0,df,fHighCut,y,ny): # etaBC generation

	f=np.arange(f0,fHighCut+f0,df)

	omega=2*np.pi*f

	JS = np.zeros((1,f.size))

	for ij in range(0,f.size-1):

		fL=f[ij]

		JS1 = jonswap(fL,Hs,Tp)

		JS[0,ij] = JS1

	#tSpan=0:dt:TDur;
	tSpan=np.arange(0,TDur+dt,dt)

	etaBC=np.zeros((tSpan.size,1))

	A=np.zeros((1,omega.size))
	B=np.zeros((1,omega.size))
	AB=np.random.standard_normal((1,2*omega.size)) #random Fourie coefficients

	for j in range(0,omega.size):

	    A[0,j]=np.sqrt(JS[0,j]*df)*AB[0,j]
	    B[0,j]=np.sqrt(JS[0,j]*df)*AB[0,omega.size+j]

	for i in range(0,tSpan.size):

		etaBC[i,0]=np.sum(A*np.cos(2*np.pi*f*tSpan[i])+B*np.sin(2*np.pi*f*tSpan[i])); # Initial Wave Surface

	# Print Check
	#print omega.size

	#print etaBC
	#plt.plot(tSpan,etaBC,'b-*')
	#plt.xlabel('Time[s]')
	#plt.ylabel('Eta[m]')
	#plt.grid()
	#plt.show()

	n = tSpan.size

	# Lets print output the Wave Maker

	file = open("waveMakerSignalrandom.inp","w")

	file.write("# This is a Wave Generation surface response at x=0\n")
	file.write("%.7f %.0f %.0f\n" % (dt, n, ny))
	file.write("%.7f\n" % y)

	for i in range(0,tSpan.size):
	  file.write("%.7f %.7f\n" % (tSpan[i],etaBC[i,0]))

	file.close()

	## Which Fourie coefficients have been used

	file = open("randomAB.txt","w")

	file.write("# These are random Aj and Bj\n")

	for i in range(0,omega.size):
	  file.write("%.7s %.7s\n" % (AB[0,i],AB[0,omega.size+i]))

	file.close()


"""
Function composition
====================

This example shows the composition of multidimensional FDataGrids.
"""

# Author: Pablo Marcos Manchón
# License: MIT

# sphinx_gallery_thumbnail_number = 3

import skfda

from mpl_toolkits.mplot3d import axes3d

import numpy as np

##############################################################################
# Function composition can be applied to our data once is in functional
# form using the method :func:`~skfda.representation.FData.compose`.
#
# Let :math:`f: X \rightarrow Y` and :math:`g: Y \rightarrow Z`, the
# composition will produce a third function :math:`g \circ f: X \rightarrow Z`
# which maps :math:`x \in X` to :math:`g(f(x))` [1].
#
# In :ref:`sphx_glr_auto_examples_plot_landmark_registration.py` it is shown
# the simplest case, where it is used to apply a transformation of the time
# scale of unidimensional data to register its features.
#
# The following example shows the basic usage applied to a surface and a
# curve, although the method will work for data with arbitrary dimensions to.
#
# Firstly we will create a data object containing a surface
# :math:`g: \mathbb{R}^2 \rightarrow \mathbb{R}`.
#
# Constructs example surface
X, Y, Z = axes3d.get_test_data(1.2)
data_matrix = [Z.T]
grid_points = [X[0, :], Y[:, 0]]

g = skfda.FDataGrid(data_matrix, grid_points)

# Sets cubic interpolation
g.interpolation = skfda.representation.interpolation.SplineInterpolation(
    interpolation_order=3)

# Plots the surface
g.plot()

##############################################################################
# We will create a parametric curve
# :math:`f(t)=(10 \, \cos(t), 10 \, sin(t))`. The result of the composition,
# :math:`g \circ f:\mathbb{R} \rightarrow \mathbb{R}` will be another
# functional object with the values of :math:`g` along the path given by
# :math:`f`.
#

# Creation of circunference in parametric form
t = np.linspace(0, 2 * np.pi, 100)

data_matrix = [10 * np.array([np.cos(t), np.sin(t)]).T]
f = skfda.FDataGrid(data_matrix, t)

# Composition of function
gof = g.compose(f)

gof.plot()

##############################################################################
# In the following chart it is plotted the curve
# :math:`(10 \, \cos(t), 10 \, sin(t), g \circ f (t))` and the surface.
#

# Plots surface
fig = g.plot(alpha=.8)

# Plots path along the surface
path = f(t)[0]
fig.axes[0].plot(path[:, 0], path[:, 1], gof(t)[0, ..., 0], color="orange")

fig

##############################################################################
# [1] Function composition `https://en.wikipedia.org/wiki/Function_composition
# <https://en.wikipedia.org/wiki/Function_composition>`_.
#


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

import numpy as np
from time import time
import math

def is_prime(x):
    return 0 not in [x % i for i in range(2, int(math.sqrt(x)) + 1)]

def is_prime3(x):
    flag = True
    for p in p_list2:
        if p > math.sqrt(x):
            break
        if x % p == 0:
            flag = False
            break
    if flag:
        p_list2.append(x)
    return flag

if __name__ == "__main__":
    a = 2
    b = 1000

    # 方法1：直接计算
    t = time()
    p = [p for p in range(a, b) if 0 not in [p % d for d in range(2, int(math.sqrt(p)) + 1)]]
    print(time() - t)
    print(p)

    # 方法2：利用filter
    t = time()
    p = list(filter(is_prime, list(range(a, b))))
    print(time() - t)
    print(p)

    # 方法3：利用filter和lambda
    t = time()
    is_prime2 = (lambda x: 0 not in [x % i for i in range(2, int(math.sqrt(x)) + 1)])
    p = list(filter(is_prime2, list(range(a, b))))
    print(time() - t)
    print(p)

    # 方法4：定义
    t = time()
    p_list = []
    for i in range(2, b):
        flag = True
        for p in p_list:
            if p > math.sqrt(i):
                break
            if i % p == 0:
                flag = False
                break
        if flag:
            p_list.append(i)
    print(time() - t)
    print(p_list)

    # 方法5：定义和filter
    p_list2 = []
    t = time()
    list(filter(is_prime3, list(range(2, b))))
    print(time() - t)
    print(p_list2)

    print('---------------------')
    a = 750
    b = 900
    p_list2 = []
    np.set_printoptions(linewidth=150)
    p = np.array(list(filter(is_prime3, list(range(2, b+1)))))
    p = p[p >= a]
    print(p)
    p_rate = float(len(p)) / float(b-a+1)
    print('素数的概率：', p_rate, end='\t  ')
    print('公正赔率：', 1/p_rate)
    print('合数的概率：', 1-p_rate, end='\t  ')
    print('公正赔率：', 1 / (1-p_rate))

    alpha1 = 5.5 * p_rate
    alpha2 = 1.1 * (1 - p_rate)
    print('赔率系数：', alpha1, alpha2)
    print(1 - (alpha1 + alpha2) / 2)
    print((1 - alpha1) * p_rate + (1 - alpha2) * (1 - p_rate))


import matplotlib.pyplot as plt
import numpy as np
import numpy.linalg as LA
import os

PLOT_COLORS = ['red', 'green', 'blue', 'orange']  # Colors for your plots
K = 4           # Number of Gaussians in the mixture model
NUM_TRIALS = 3  # Number of trials to run (can be adjusted for debugging)
UNLABELED = -1  # Cluster label for unlabeled data points (do not change)

def main(is_semi_supervised, trial_num):
    """Problem 3: EM for Gaussian Mixture Models (unsupervised and semi-supervised)"""
    print('Running {} EM algorithm...'
          .format('semi-supervised' if is_semi_supervised else 'unsupervised'))

    # Load dataset
    train_path = os.path.join('.', 'train.csv')
    x_all, z_all = load_gmm_dataset(train_path)

    # Split into labeled and unlabeled examples
    labeled_idxs = (z_all != UNLABELED).squeeze()
    x_tilde = x_all[labeled_idxs, :]   # Labeled examples
    z_tilde = z_all[labeled_idxs, :]   # Corresponding labels
    x = x_all[~labeled_idxs, :]        # Unlabeled examples

    # Initialize parameters phi, mu, sigma
    n_examples, dim = x_all.shape
    clustering = np.random.randint(K, size=n_examples)
    phi = np.ones(K) / K
    mu = np.empty([K, dim])
    sigma = np.empty([K, dim, dim])
    for j in range(K):
        x_j = x_all[clustering == j]
        mu[j] = np.mean(x_j, axis=0)
        sigma[j] = (x_j - mu[j]).T @ (x_j - mu[j]) / len(x_j)

    if is_semi_supervised:
        w = run_semi_supervised_em(x, x_tilde, z_tilde, phi, mu, sigma)
    else:
        w = run_em(x, phi, mu, sigma)

    # Plot your predictions
    z_pred = np.argmax(w, axis=1)
    plot_gmm_preds(x, z_pred, is_semi_supervised, plot_id=trial_num)

def run_em(x, phi, mu, sigma):
    """Problem 3(d): EM Algorithm (unsupervised).

    See inline comments for instructions.

    Args:
        x: Design matrix of shape (n_examples, dim).
        phi: Initial mixture prior, of shape (k,).
        mu: Initial cluster means, of shape (k, dim).
        sigma: Initial cluster covariances, of shape (k, dim, dim).

    Returns:
        Updated weight matrix of shape (n_examples, k) resulting from EM algorithm.
        More specifically, w[i, j] should contain the probability of
        example x^(i) belonging to the j-th Gaussian in the mixture.
    """
    eps = 1e-3    # Convergence threshold
    max_iter = 2000
    n_examples, dim = x.shape

    ll = prev_ll = - np.inf
    log_prob = np.empty([n_examples, K])

    for i in range(max_iter):
        # Do E-step
        for j in range(K):
            exponents = (x - mu[j]) @ LA.inv(sigma[j]) * (x - mu[j])
            exponents = exponents.sum(axis=1)
            log_prob[:,j] = - np.log(LA.det(sigma[j])) / 2 - exponents / 2 + np.log(phi[j])
        w = log_prob - logsumexp(log_prob).reshape(-1, 1)
        w = np.exp(w)

        # Check convergence
        # Stop when the absolute change in log-likelihood is < eps
        ll = - n_examples * dim / 2 * np.log(2 * np.pi) + np.sum(logsumexp(log_prob))
        if np.abs(ll - prev_ll) < eps:
            print(f'Converged after {i + 1} iterations\nwith ll loss {ll:.2f}\n')
            break
        prev_ll = ll

        # Do M-step
        phi = np.sum(w, axis=0) / n_examples
        for j in range(K):
            mu[j] = w[:,j] @ x / np.sum(w[:,j])
            sigma[j] = w[:,j] * (x - mu[j]).T @ (x - mu[j]) / np.sum(w[:,j])

    return w

def run_semi_supervised_em(x, x_tilde, z_tilde, phi, mu, sigma):
    """Problem 3(e): Semi-Supervised EM Algorithm.

    See inline comments for instructions.

    Args:
        x: Design matrix of unlabeled examples of shape (n_examples_unobs, dim).
        x_tilde: Design matrix of labeled examples of shape (n_examples_obs, dim).
        z_tilde: Array of labels of shape (n_examples_obs, 1).
        phi: Initial mixture prior, of shape (k,).
        mu: Initial cluster means, of shape (k, dim).
        sigma: Initial cluster covariances, of shape (k, dim, dim).

    Returns:
        Updated weight matrix of shape (n_examples, k) resulting from semi-supervised EM algorithm.
        More specifically, w[i, j] should contain the probability of
        example x^(i) belonging to the j-th Gaussian in the mixture.
    """
    alpha = 20.                   # Weight for supervised objective
    eps = 1e-3                    # Convergence threshold
    max_iter = 2000
    n0, dim = x.shape             # for unobserved examples
    n1 = x_tilde.shape[0]         # for observed examples
    num_total = n0 + n1

    x = np.vstack([x, x_tilde])   # new x contains all examples
    w1 = alpha * (z_tilde == np.arange(K))    # weights for observed examples

    ll = prev_ll = - np.inf
    log_prob = np.empty([num_total, K])

    for it in range(max_iter):
        # Do E-step
        for j in range(K):
            exponents = (x - mu[j]) @ LA.inv(sigma[j]) * (x - mu[j])
            exponents = exponents.sum(axis=1)
            log_prob[:, j] = - np.log(LA.det(sigma[j])) / 2 - exponents / 2 + np.log(phi[j])
        w = log_prob - logsumexp(log_prob).reshape(-1, 1)
        w = np.exp(w)

        # Check convergence
        # Stop when the absolute change in log-likelihood is < eps
        ll = (- num_total * dim / 2 * np.log(2 * np.pi)
              + np.sum(logsumexp(log_prob[:-n1]))
              + np.sum(w1 * log_prob[-n1:]))
        if np.abs(ll - prev_ll) < eps:
            print(f'Converged after {it + 1} iterations\nwith ll loss {ll:.2f}\n')
            break
        prev_ll = ll
        w[-n1:] = w1

        # Do M-step
        phi = np.sum(w, axis=0) / (n0 + alpha * n1)
        for j in range(K):
            mu[j] = w[:, j] @ x / np.sum(w[:, j])
            sigma[j] = w[:, j] * (x - mu[j]).T @ (x - mu[j]) / np.sum(w[:, j])

    return w

def logsumexp(z):
    """Compute the logsumexp function for each row of z."""
    z_max = np.max(z, axis=1, keepdims=True)
    exp_z = np.exp(z - z_max)
    sum_exp_z = np.sum(exp_z, axis=1)
    return z_max.squeeze() + np.log(sum_exp_z)

def plot_gmm_preds(x, z, with_supervision, plot_id):
    """Plot GMM predictions on a 2D dataset `x` with labels `z`.

    Write to the output directory, including `plot_id`
    in the name, and appending 'ss' if the GMM had supervision.

    NOTE: You do not need to edit this function.
    """
    plt.figure(figsize=(7.2, 4.8))
    plt.xlabel('x_1')
    plt.ylabel('x_2')

    for x_1, x_2, z_ in zip(x[:, 0], x[:, 1], z):
        color = 'gray' if z_ < 0 else PLOT_COLORS[int(z_)]
        alpha = 0.25 if z_ < 0 else 0.5
        plt.scatter(x_1, x_2, marker='.', s=40, c=color, alpha=alpha)

    if with_supervision:
        file_name = f'semisup_gmm{plot_id}.png'
    else:
        file_name = f'unsup_gmm{plot_id}.png'
    save_path = os.path.join('.', file_name)
    plt.savefig(save_path)

def load_gmm_dataset(csv_path):
    """Load dataset for Gaussian Mixture Model.

    Args:
         csv_path: Path to CSV file containing dataset.

    Returns:
        x: NumPy array shape (n_examples, dim)
        z: NumPy array shape (n_exampls, 1)

    NOTE: You do not need to edit this function.
    """

    # Load headers
    with open(csv_path, 'r') as csv_fh:
        headers = csv_fh.readline().strip().split(',')

    # Load features and labels
    x_cols = [i for i in range(len(headers)) if headers[i].startswith('x')]
    z_cols = [i for i in range(len(headers)) if headers[i] == 'z']

    x = np.loadtxt(csv_path, delimiter=',', skiprows=1, usecols=x_cols, dtype=float)
    z = np.loadtxt(csv_path, delimiter=',', skiprows=1, usecols=z_cols, dtype=float)

    if z.ndim == 1:
        z = np.expand_dims(z, axis=-1)

    return x, z

if __name__ == '__main__':
    np.random.seed(229)
    # Run NUM_TRIALS trials to see how different initializations
    # affect the final predictions with and without supervision
    for t in range(NUM_TRIALS):
        main(is_semi_supervised=False, trial_num=t)
        main(is_semi_supervised=True, trial_num=t)