"""
Implementation of SVM using cvxopt package. Implementation uses
soft margin and I've defined linear, polynomial and gaussian kernels.

To understand the theory (which is a bit challenging) I recommend reading the following:
http://cs229.stanford.edu/notes/cs229-notes3.pdf
https://www.youtube.com/playlist?list=PLoROMvodv4rMiGQp3WXShtMGgzqpfVfbU (Lectures 6,7 by Andrew Ng)

To understand how to reformulate the optimization problem we obtain
to get the input to cvxopt QP solver this blogpost can be useful:
https://xavierbourretsicotte.github.io/SVM_implementation.html

Programmed by Aladdin Persson <aladdin.persson at hotmail dot com>
*    2020-04-26 Initial coding

"""

import numpy as np
import cvxopt
from utils import create_dataset, plot_contour

def linear(x, z):
    return np.dot(x, z.T)

def polynomial(x, z, p=5):
    return (1 + np.dot(x, z.T)) ** p

def gaussian(x, z, sigma=0.1):
    return np.exp(-np.linalg.norm(x - z, axis=1) ** 2 / (2 * (sigma ** 2)))

class SVM:
    def __init__(self, kernel=gaussian, C=1):
        self.kernel = kernel
        self.C = C

    def fit(self, X, y):
        self.y = y
        self.X = X
        m, n = X.shape

        # Calculate Kernel
        self.K = np.zeros((m, m))
        for i in range(m):
            self.K[i, :] = self.kernel(X[i, np.newaxis], self.X)

        # Solve with cvxopt final QP needs to be reformulated
        # to match the input form for cvxopt.solvers.qp
        P = cvxopt.matrix(np.outer(y, y) * self.K)
        q = cvxopt.matrix(-np.ones((m, 1)))
        G = cvxopt.matrix(np.vstack((np.eye(m) * -1, np.eye(m))))
        h = cvxopt.matrix(np.hstack((np.zeros(m), np.ones(m) * self.C)))
        A = cvxopt.matrix(y, (1, m), "d")
        b = cvxopt.matrix(np.zeros(1))
        cvxopt.solvers.options["show_progress"] = False
        sol = cvxopt.solvers.qp(P, q, G, h, A, b)
        self.alphas = np.array(sol["x"])

    def predict(self, X):
        y_predict = np.zeros((X.shape[0]))
        sv = self.get_parameters(self.alphas)

        for i in range(X.shape[0]):
            y_predict[i] = np.sum(
                self.alphas[sv]
                * self.y[sv, np.newaxis]
                * self.kernel(X[i], self.X[sv])[:, np.newaxis]
            )

        return np.sign(y_predict + self.b)

    def get_parameters(self, alphas):
        threshold = 1e-5

        sv = ((alphas > threshold) * (alphas < self.C)).flatten()
        self.w = np.dot(X[sv].T, alphas[sv] * self.y[sv, np.newaxis])
        self.b = np.mean(
            self.y[sv, np.newaxis]
            - self.alphas[sv] * self.y[sv, np.newaxis] * self.K[sv, sv][:, np.newaxis]
        )
        return sv

if __name__ == "__main__":
    np.random.seed(1)
    X, y = create_dataset(N=50)

    svm = SVM(kernel=gaussian)
    svm.fit(X, y)
    y_pred = svm.predict(X)
    plot_contour(X, y, svm)

    print(f"Accuracy: {sum(y==y_pred)/y.shape[0]}")


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

class Bezier:
    """
    Bezier curve interpolation around points

        Attributes:
            n: The number of points around which it will be interpolated
            points: The coordinate of the points around which it will be interpolated
            curve_pts_num: The number of points on a Bezier curve between two points
    """
    n = None
    points = None
    curve_pts_num = None
    curve_pts = None
    C = None
    P = None
    A = None
    B = None

    def __init__(self, points, curve_pts_num = 30):
        """
        Initializes the class

            Parameters:
                points: The coordinate of the points around which it will be interpolated
                curve_pts_num: The number of points on a Bezier curve between two points
        """
        self.n = len(points)
        self.points = points
        self.curve_pts_num = curve_pts_num
        self.fixVariables()

    def fixVariables(self):
        """
        Fixes the type of the variables
        """
        if type(self.points) != np.ndarray:
            self.points = np.array(self.points)

    def createCoefficientMatrix(self):
        """
            Creates the coefficient matrix for the Bezier curve interpolation
        """
        C = np.zeros((self.n, self.n))

        for i in range(self.n):
            r = i + 1 if i + 1 < self.n else (i + 1) % self.n
            row = np.zeros(self.n)
            row[i], row[r] = 1, 2
            C[i] = row

        self.C = C

    def createEndPointVector(self):
        """
        Creates the column vector which contains the end points of each curve connecting two points
        """
        P = np.zeros((self.n, 2))

        for i in range(self.n):
            l = i + 1 if i + 1 < self.n else (i + 1) % self.n
            r = i + 2 if i + 2 < self.n else (i + 2) % self.n

            val = 2 * self.points[l] + self.points[r]
            P[i] = val

        self.P = P

    def findControlPoints(self):
        """
        Find the control points for the Bezier curve
        """
        A = np.linalg.solve(self.C, self.P)
        B = np.zeros_like(A)

        for i in range(self.n):
            l = i + 1 if i + 1 < self.n else (i + 1) % self.n
            B[i] = 2 * self.points[l] - A[l]

        self.A = A
        self.B = B

    def findPoints(self):
        """
        Finds the points on the smooth curve
        """
        self.createCoefficientMatrix()
        self.createEndPointVector()
        self.findControlPoints()

        all_pts = []

        for i in range(self.n):
            next_i = i + 1 if i + 1 < self.n else (i + 1) % self.n
            dpts = np.linspace(0, 1, self.curve_pts_num)
            for j in dpts:
                pt = np.power(1 - j, 3) * self.points[i] + 3 * j * np.power(1 - j, 2) * self.A[i] + 3 * (1 - j) * np.power(j, 2) * self.B[i] + np.power(j, 3) * self.points[next_i]
                all_pts.append(pt.tolist())

        self.curve_pts = np.array(all_pts)

    def getPoints(self):
        """
        Return the points on the curve. If they haven't been computed, compute them
        """
        if self.curve_pts == None:
            self.findPoints()

        return self.curve_pts

    def draw(self):
        """
        Draws a plot of the curve and the points
        """
        x, y = self.curve_pts[:,0], self.curve_pts[:,1]
        px, py = self.points[:,0], self.points[:,1]
        plt.plot(x, y, "b-")
        plt.plot(px, py, "ko")
        plt.axes().set_aspect('equal')
        plt.show()


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

# theta''(t) + b*theta'(t) + c*sin(theta(t)) = 0
# theta'(t) = omega(t)
# omega'(t) = -b*omega(t) - c*sin(theta(t))

def pend(y, t, b, c):
    theta, omega = y
    dydt = [omega, -b*omega - c*np.sin(theta)]
    return dydt

b = 0.25
c = 5.0

y0 = [np.pi - 0.1, 0.0]

t = np.linspace(0, 10, 101)

sol = odeint(pend, y0, t, args=(b, c))

plt.plot(t, sol[:, 0], 'b', label='theta(t)')
plt.plot(t, sol[:, 1], 'g', label='omega(t)')
plt.legend(loc='best')
plt.xlabel('t')
plt.grid()
plt.show()


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

# # Scenario Analysis: Pop Up Shop
#
# ![](https://upload.wikimedia.org/wikipedia/commons/thumb/c/c5/Weich_Couture_Alpaca%2C_D%C3%BCsseldorf%2C_December_2020_%2809%29.jpg/300px-Weich_Couture_Alpaca%2C_D%C3%BCsseldorf%2C_December_2020_%2809%29.jpg)
#
# Kürschner (talk) 17:51, 1 December 2020 (UTC), CC0, via Wikimedia Commons

# In[1]:

# install Pyomo and solvers for Google Colab
import sys
if "google.colab" in sys.modules:
    get_ipython().system('wget -N -q https://raw.githubusercontent.com/jckantor/MO-book/main/tools/install_on_colab.py ')
    get_ipython().run_line_magic('run', 'install_on_colab.py')

# ## The problem
#
# There is an opportunity to operate a pop-up shop to sell a unique commemorative item for events held at a famous location. The items cost 12 € each and will selL for 40 €. Unsold items can be returned to the supplier at a value of only 2 € due to their commemorative nature.
#
# | Parameter | Symbol | Value |
# | :---: | :---: | :---: |
# | sales price | $r$ | 40 € |
# | unit cost | $c$ | 12 € |
# | salvage value | $w$ | 2 € |
#
# Profit will increase with sales. Demand for these items, however, will be high only if the weather is good. Historical data suggests the following scenarios.

# | Scenario ($s$) | Demand ($d_s$) | Probability ($p_s$) |
# | :---: | :-----: | :----------: |
# | Sunny Skies | 650 | 0.10 |
# | Good Weather | 400 | 0.60 |
# | Poor Weather | 200 | 0.30 |
#
# The problem is to determine how many items to order for the pop-up shop.
#
# The dilemma is that the weather won't be known until after the order is placed. Ordering enough items to meet demand for a good weather day results in a  financial penalty on returned goods if the weather is poor. But ordering just enough items to satisfy demand on a poor weather day leaves "money on the table" if the weather is good.
#
# How many items should be ordered for sale?

# ## Expected value for the mean scenario (EVM)
#
# A naive solution to this problem is to place an order equal to the expected demand. The expected demand is given by
#
# $$
# \begin{align*}
# \mathbb E[D] & = \sum_{s\in S} p_s d_s
# \end{align*}
# $$
#
# Choosing an order size $x = \mathbb E[d]$ results in an expected profit we call the **expected value of the mean scenario (EVM)**.
#
# Variable $y_s$ is the actual number of items sold if scenario $s$ should occur. The number sold is the lesser of the demand $d_s$ and the order size $x$.
#
# $$
# \begin{align*}
# y_s & = \min(d_s, x) & \forall s \in S
# \end{align*}
# $$
#
# Any unsold inventory $x - y_s$ remaining after the event will be sold at the salvage price $w$. Taking into account the revenue from sales $r y_s$, the salvage value of the unsold inventory $w(x - y_s)$, and the cost of the order $c x$, the profit $f_s$ for scenario $s$ is given by
#
# $$
# \begin{align*}
# f_s & = r y_s + w (x - y_s) - c  x & \forall s \in S
# \end{align*}
# $$
#
# The average or expected profit is given by
#
# $$
# \begin{align*}
# \text{EVM} = \mathbb E[f] & = \sum_{s\in S} p_s f_s
# \end{align*}
# $$
#
# These calculations can be executed using operations on the pandas dataframe. Let's begin by calculating the expected demand.
#
# Below we create a pandas DataFrame object to store the scenario data.

# In[7]:

import numpy as np
import pandas as pd

# price information
r = 40
c = 12
w = 2

# scenario information
scenarios = {
    "sunny skies" : {"probability": 0.10, "demand": 650},
    "good weather": {"probability": 0.60, "demand": 400},
    "poor weather": {"probability": 0.30, "demand": 200},
}

df = pd.DataFrame.from_dict(scenarios).T
display(df)

# In[8]:

expected_demand = sum(df["probability"] * df["demand"])
print(f"Expected demand = {expected_demand}")

# Subsequent calculations can be done directly withthe  pandas dataframe holding the scenario data.

# In[9]:

df["order"] = expected_demand
df["sold"] = df[["demand", "order"]].min(axis=1)
df["salvage"] = df["order"] - df["sold"]
df["profit"] = r * df["sold"] + w * df["salvage"] - c * df["order"]

EVM = sum(df["probability"] * df["profit"])

print(f"Mean demand = {expected_demand}")
print(f"Expected value of the mean demand (EVM) = {EVM}")
display(df)

# ## Expected value of the stochastic solution (EVSS)
#
# The optimization problem is to find the order size $x$ that maximizes expected profit subject to operational constraints on the decision variables. The variables $x$ and $y_s$ are non-negative integers, while $f_s$ is a real number that can take either positive and negative values. The number of goods sold in scenario $s$ has to be less than the order size $x$ and customer demand $d_s$.
#
# The problem to be solved is
#
# $$
# \begin{align*}
# \text{EV} = & \max_{x, y_s} \mathbb E[F] = \sum_{s\in S} p_s f_s \\
# \text{subject to:} \\
# f_s & = r y_s + w(x - y_s) - c x & \forall s \in S\\
# y_s & \leq x & \forall s \in S \\
# y_s & \leq d_s & \forall s \in S
# \end{align*}
# $$
#
# where $S$ is the set of all scenarios under consideration.

# In[5]:

import pyomo.environ as pyo
import pandas as pd

# price information
r = 40
c = 12
w = 2

# scenario information
scenarios = {
    "sunny skies" : {"demand": 650, "probability": 0.1},
    "good weather": {"demand": 400, "probability": 0.6},
    "poor weather": {"demand": 200, "probability": 0.3},
}

# create model instance
m = pyo.ConcreteModel('Pop-up Shop')

# set of scenarios
m.S = pyo.Set(initialize=scenarios.keys())

# decision variables
m.x = pyo.Var(domain=pyo.NonNegativeIntegers)
m.y = pyo.Var(m.S, domain=pyo.NonNegativeIntegers)
m.f = pyo.Var(m.S, domain=pyo.Reals)

# objective
@m.Objective(sense=pyo.maximize)
def EV(m):
    return sum([scenarios[s]["probability"]*m.f[s] for s in m.S])

# constraints
@m.Constraint(m.S)
def profit(m, s):
    return m.f[s] == r*m.y[s] + w*(m.x - m.y[s]) - c*m.x

@m.Constraint(m.S)
def sales_less_than_order(m, s):
    return m.y[s] <= m.x

@m.Constraint(m.S)
def sales_less_than_demand(m, s):
    return m.y[s] <= scenarios[s]["demand"]

# solve
solver = pyo.SolverFactory('glpk')
results = solver.solve(m)

# display solution using Pandas
print("Solver Termination Condition:", results.solver.termination_condition)
print("Expected Profit:", m.EV())
print()
for s in m.S:
    scenarios[s]["order"] = m.x()
    scenarios[s]["sold"] = m.y[s]()
    scenarios[s]["salvage"] = m.x() - m.y[s]()
    scenarios[s]["profit"] = m.f[s]()

df = pd.DataFrame.from_dict(scenarios).T
display(df)

# Optimizing over all scenarios provides an expected profit of 8,920 €, an increase of 581 € over the base case of simply ordering the expected number of items sold. The new solution places a larger order. In poor weather conditions there will be more returns and lower profit that is more than compensated by the increased profits in good weather conditions.
#
# The addtional value that results from solve of this planning problem is called the **Value of the Stochastic Solution (VSS)**. The value of the stochastic solution is the additional profit compared to ordering to meet expected in demand. In this case,
#
# $$\text{VSS} = \text{EV} - \text{EVM} = 8,920 - 8,339 = 581$$

# ## Expected value with perfect information (EVPI)
#
# Maximizing expected profit requires the size of the order be decided before knowing what scenario will unfold. The decision for $x$ has to be made "here and now" with probablistic information about the future, but without specific information on which future will actually transpire.
#
# Nevertheless, we can perform the hypothetical calculation of what profit would be realized if we could know the future. We are still subject to the variability of weather, what is different is we know what the weather will be at the time the order is placed.
#
# The resulting value for the expected profit is called the **Expected Value of Perfect Information (EVPI)**.  The difference EVPI - EV is the extra profit due to having perfect knowledge of the future.
#
# To compute the expected profit with perfect information, we let the order variable $x$ be indexed by the subsequent scenario that will unfold. Given decision varaible $x_s$, the model for EVPI becomes
#
# $$
# \begin{align*}
# \text{EVPI} = & \max_{x_s, y_s} \mathbb E[f] = \sum_{s\in S} p_s f_s \\
# \text{subject to:} \\
# f_s & = r y_s + w(x_s - y_s) - c x_s & \forall s \in S\\
# y_s & \leq x_s & \forall s \in S \\
# y_s & \leq d_s & \forall s \in S
# \end{align*}
# $$
#
# The following implementation is a variation of the prior cell.

# In[6]:

import pyomo.environ as pyo
import pandas as pd

# price information
r = 40
c = 12
w = 2

# scenario information
scenarios = {
    "sunny skies" : {"demand": 650, "probability": 0.1},
    "good weather": {"demand": 400, "probability": 0.6},
    "poor weather": {"demand": 200, "probability": 0.3},
}

# create model instance
m = pyo.ConcreteModel('Pop-up Shop')

# set of scenarios
m.S = pyo.Set(initialize=scenarios.keys())

# decision variables
m.x = pyo.Var(m.S, domain=pyo.NonNegativeIntegers)
m.y = pyo.Var(m.S, domain=pyo.NonNegativeIntegers)
m.f = pyo.Var(m.S, domain=pyo.Reals)

# objective
@m.Objective(sense=pyo.maximize)
def EV(m):
    return sum([scenarios[s]["probability"]*m.f[s] for s in m.S])

# constraints
@m.Constraint(m.S)
def profit(m, s):
    return m.f[s] == r*m.y[s] + w*(m.x[s] - m.y[s]) - c*m.x[s]

@m.Constraint(m.S)
def sales_less_than_order(m, s):
    return m.y[s] <= m.x[s]

@m.Constraint(m.S)
def sales_less_than_demand(m, s):
    return m.y[s] <= scenarios[s]["demand"]

# solve
solver = pyo.SolverFactory('glpk')
results = solver.solve(m)

# display solution using Pandas
print("Solver Termination Condition:", results.solver.termination_condition)
print("Expected Profit:", m.EV())
print()
for s in m.S:
    scenarios[s]["order"] = m.x[s]()
    scenarios[s]["sold"] = m.y[s]()
    scenarios[s]["salvage"] = m.x[s]() - m.y[s]()
    scenarios[s]["profit"] = m.f[s]()

df = pd.DataFrame.from_dict(scenarios).T
display(df)

# ## Summary
#
# To summarize, have computed three different solutions to the problem of order size:
#
# * The expected value of the mean solution (EVM) is the expected profit resulting from ordering the number of items expected to sold under all scenarios.
#
# * The expected value of the stochastic solution (EVSS) is the expected profit found by solving an two-state optimization problem where the order size was the "here and now" decision without specific knowledge of which future scenario would transpire.
#
# * The expected value of perfect information (EVPI) is the result of a hypotherical case where knowledge of the future scenario was somehow available when then order had to be placed.
#
# For this example we found
#
# | Solution | Value (€) |
# | :------  | ----: |
# | Expected Value of the Mean Solution (EVM) | 8,399.0 |
# | Expected Value of the Stochastic Solution (EVSS) | 8,920.0 |
# | Expected Value of Perfect Information (EVPI) | 10,220.0 |
#
# These results verify our expectation that
#
# $$
# \begin{align*}
# EVM \leq EVSS \leq EVPI
# \end{align*}
# $$
#
# The value of the stochastic solution
#
# $$
# \begin{align*}
# VSS = EVSS - EVM = 581
# \end{align*}
# $$
#
# The value of perfect information
#
# $$
# \begin{align*}
# VPI = EVPI - EVSS = 1,300
# \end{align*}
# $$
#
#
# As one might expect, there is a cost that results from lack of knowledge about an uncertain future.


''' These give the derivations for Euler angles to rotation matrix and
Euler angles to quaternion.  We use the rotation matrix derivation only
in the tests.  The quaternion derivation is in the tests, and,
in more compact form, in the ``euler2quat`` code.

The rotation matrices operate on column vectors, thus, if ``R`` is the
3x3 rotation matrix, ``v`` is the 3 x N set of N vectors to be rotated,
and ``vdash`` is the matrix of rotated vectors::

   vdash = np.dot(R, v)

'''

from sympy import Symbol, cos, sin
from sympy.matrices import Matrix

def x_rotation(theta):
    ''' Rotation angle `theta` around x-axis
    http://en.wikipedia.org/wiki/Rotation_matrix#Dimension_three
    '''
    return Matrix([[1, 0, 0],
                   [0, cos(theta), -sin(theta)],
                   [0, sin(theta), cos(theta)]])

def y_rotation(theta):
    ''' Rotation angle `theta` around y-axis
    http://en.wikipedia.org/wiki/Rotation_matrix#Dimension_three
    '''
    return Matrix([[cos(theta), 0, sin(theta)],
                  [0, 1, 0],
                  [-sin(theta), 0, cos(theta)]])

def z_rotation(theta):
    ''' Rotation angle `theta` around z-axis
    http://en.wikipedia.org/wiki/Rotation_matrix#Dimension_three
    '''
    return Matrix([[cos(theta), -sin(theta), 0],
                  [sin(theta), cos(theta), 0],
                  [0, 0, 1]])

def qmult(q1, q2):
    ''' Multiply two quaternions

    Parameters
    ----------
    q1 : 4 element sequence
    q2 : 4 element sequence

    Returns
    -------
    q12 : shape (4,) array

    Notes
    -----
    See : http://en.wikipedia.org/wiki/Quaternions#Hamilton_product
    '''
    w1, x1, y1, z1 = q1
    w2, x2, y2, z2 = q2
    w = w1*w2 - x1*x2 - y1*y2 - z1*z2
    x = w1*x2 + x1*w2 + y1*z2 - z1*y2
    y = w1*y2 + y1*w2 + z1*x2 - x1*z2
    z = w1*z2 + z1*w2 + x1*y2 - y1*x2
    return w, x, y, z

def quat_around_axis(theta, axis):
    ''' Quaternion for rotation of angle `theta` around axis `axis`

    Parameters
    ----------
    theta : symbol
       angle of rotation
    axis : 3 element sequence
       vector (assumed normalized) specifying axis for rotation

    Returns
    -------
    quat : 4 element sequence of symbols
       quaternion giving specified rotation

    Notes
    -----
    Formula from http://mathworld.wolfram.com/EulerParameters.html
    '''
    # axis vector assumed normalized
    t2 = theta / 2.0
    st2 = sin(t2)
    return (cos(t2),
            st2 * axis[0],
            st2 * axis[1],
            st2 * axis[2])

def quat2mat(quat):
    ''' Symbolic conversion from quaternion to rotation matrix

    For a unit quaternion

    From: http://en.wikipedia.org/wiki/Rotation_matrix#Quaternion
    '''
    w, x, y, z = quat
    return Matrix([
            [1 - 2*y*y-2*z*z, 2*x*y - 2*z*w, 2*x*z+2*y*w],
            [2*x*y+2*z*w, 1-2*x*x-2*z*z, 2*y*z-2*x*w],
            [2*x*z-2*y*w, 2*y*z+2*x*w, 1-2*x*x-2*y*y]])

# Formula for rotation matrix given Euler angles and z, y, x ordering
M_zyx = (x_rotation(Symbol('x')) *
         y_rotation(Symbol('y')) *
         z_rotation(Symbol('z')))

# Formula for quaternion given Euler angles, z, y, x ordering
q_zrot = quat_around_axis(Symbol('z'), [0, 0, 1])
q_yrot = quat_around_axis(Symbol('y'), [0, 1, 0])
q_xrot = quat_around_axis(Symbol('x'), [1, 0, 0])

q_zyx = qmult(q_xrot, qmult(q_yrot, q_zrot))


import numpy as np
import cv2

# 1. Create a vector of 10 floats (zeros)
def e1():
    return np.zeros(10)

# 2. Create a vector of 10 float (zeros) whose 5th element is one
def e2():
    arr = e1()
    arr[5] = 1
    return arr

# 3. Create a vector of integers going from 10 to 49
def e3():
    return np.arange(10, 50)

# 4. Create a matrix of 3x3 floats going from 1 to 9
def e4():
    arr = np.arange(1,10)
    return arr.reshape(3,3)

# 5. Create a matrix of 3x3 floats going from 1 to 9 and flip it horizontally
def e5():
    return np.flip(e4(), 1)

# 6. Create a matrix of 3x3 floats going from 1 to 9 and flip it vertically
def e6():
    return np.flip(e4(), 0)

# 7. Create a 3x3 identity matrix
def e7():
    return np.identity(3)

# 8. Create a 3x3 matrix of random values
def e8():
    return np.random.random_sample((3,3))

# 9. Create a random vector of 10 numbers and compute the mean value
def e9():
    arr = np.random.randint(0, 100, 10)
    print('Mean = {}'.format(np.mean(arr)))
    return arr

# 10. Create a 10x10 array of zeros surrounded/framed by ones
def e10():
    arr = np.ones((10,10))
    arr[1:9,1:9] = 0 # arr[1:-1,1:-1] = 0
    return arr

# 11. Create a 5x5 matrix of rows from 1 to 5
def e11():
    arr = np.zeros((5,5))
    arr[:] = np.arange(1,6)
    return arr

# 12. Create an array of 9 random integers and reshape it to a 3x3 matrix of floats
def e12():
    arr = np.random.randint(0, 9, 9)
    arr.reshape((3,3))
    return arr.astype(float)

# 13. Create a 5x5 matrix of random values and subtract its average from it
def e13():
    arr = np.random.random_sample((5,5))
    print("Mean: {}".format(np.mean(arr)))
    return arr

# 14. Create a 5x5 matrix of random values and subtract the average of each row to each row
def e14():
    np.random.seed(123)
    arr = np.random.random_sample((5,5))
    for i in range(5):
        print("Mean{}: {}".format(i, np.mean(arr[i])))
    return arr

# 15. Create an array of 5x5 random values and return the value that is closer to 0.5
def e15():
    np.random.seed(123)
    arr = np.random.random_sample((5, 5))
    arr = arr.flatten()
    index = (np.abs(arr - 0.5)).argmin()
    return arr[index]

# 16. Make a 3x3 matrix of random numbers from 0 to 10 and count how many of them are > 5
def e16():
    np.random.seed(123)
    arr = np.random.randint(0, 11, (3, 3))
    return arr[arr > 5]

# 17. Create a horizontal gradient image of 64x64 that goes from black to white
def e17():
    img = np.zeros((64, 64), np.uint8)
    img[:] = np.arange(0, 255, 255/64)
    cv2.imshow('Degradado b/n', img)
    cv2.waitKey(0)

# 18. Create a vertical gradient image of 64x64 that goes from black to white
def e18():
    img = np.zeros((64, 64), np.float)
    c = np.arange(0.0, 64.0)
    print(c)
    c = c/64.0
    print(c)
    img[0, :] = c
    cv2.imshow('Degradado b/n', img)
    cv2.waitKey(0)
# 19. Create a 3-component white image of 64x64 pixels and set the blue component to zero
# (the result should be yellow)
# 20. Create a 3-component white image of 64x64 pixels, set the blue component of the
# top-left part to zero (the result should be yellow) and the red component of the
# bottom-right part to zero (the result should be cyan
# 21. Open an image and insert black horizontal scan lines at 50%
# 22. Open an image and insert black vertical scan lines at 50%
# 23. Open an image, convert it to float64, normalize it, darken it 50%, and show it

#print(e17())
e18()


#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time     : 2018/09/19 15:10
# @Author   : Iydon
# @File     : 2.3.py
# @Abstract : Homework auxiliary code.
import numpy as np

def Newton_method(f, df, start:float=0.0, step:int=1)->float:
	"""
	From 2.2.py.
	"""
	fun = lambda x: x-f(x)/df(x)
	if step:
		val = fun(start)
		for i in range(1,step):
			val = fun(val)
		return val
	else:
		return start

def secant_method(f, start:list, step:int=1) -> float:
    """
    From 3.py.
    """
    p = [i    for i in start]
    q = [f(i) for i in start]
    for i in range(step):
    	_p = p[-1] - q[-1]*(p[-1]-p[0])/(q[-1]-q[0])
    	p = [p[-1], _p]
    	q = [q[-1], f(_p)]
    return _p

def false_position(f, start:list, step:int=1) -> float:
    """
    From 3.py.
    """
    p = [i    for i in start]
    q = [f(i) for i in start]
    for i in range(step):
    	_p = p[-1] - q[-1]*(p[-1]-p[0])/(q[-1]-q[0])
    	_q = f(_p)
    	if _q*q[-1] < 0:
    		p[0] = p[-1]
    		q[0] = q[-1]
    	p[-1] = _p
    	q[-1] = _q
    return False

# ------- HOMEWORK -------
f  = lambda x: x**2-6
df = lambda x: 2*x
result = Newton_method(f, df, 1, 2)
print(result)

f  = lambda x: -x**3-np.cos(x)
df = lambda x: -3*x**2+np.sin(x)
result = Newton_method(f, df, -1, 2)
print(result)

f = lambda x: -x**3-np.cos(x)
result = secant_method(f, [-1,0], 2)
print(result)


import numpy as np
import matplotlib.pyplot as plt
from KnotVectors import OpenUniformKnotVector, PeriodicKnotVector
from BSpline import BSpline

#returns P which corresponds to multiplicity of each knot vector value
#and s which is the number of knot vector values that have multiple occurences
def KnotVectorMultiplicity(Knots):
    V, P = np.unique(Knots, False, False, True)
    s = np.sum(P[1:-1] > 1) #discard first/last since s only cares about internal values
    return V, P, s

def RaiseOrderTwoToThree(OriginalPoints, OriginalKnots):
    Values, P, s = KnotVectorMultiplicity(OriginalKnots)
    countPoints = np.size(OriginalPoints, axis=0)
    dimension = np.size(OriginalPoints, 1)
    countNewPoints = countPoints + 3 + s #3 is the new order
    NewPoints = np.zeros([countNewPoints, dimension])

    mpts = 0

    if OriginalKnots[0] < OriginalKnots[1]:
        NewPoints[0, :] = OriginalPoints[0, :] * 0.5
        mpts += 1

    NewPoints[mpts, :] = OriginalPoints[0, :]

    for i in range(1, countPoints):
        if OriginalKnots[i] < OriginalKnots[i + 1]:
            mpts += 1
            NewPoints[mpts, :] = (OriginalPoints[i, :] + OriginalPoints[i - 1, :]) * 0.5
        mpts += 1
        NewPoints[mpts, :] = OriginalPoints[i, :]

    if OriginalKnots[countPoints] < OriginalKnots[countPoints + 1]:
        mpts += 1
        NewPoints[mpts, :] = OriginalPoints[countPoints - 1, :] * 0.5

    NewKnots = np.asarray([])
    countP = len(P)
    for i in range(countP):
        NewKnots = np.append(NewKnots, np.ones(P[i] + 1) * Values[i], axis=0) #Duplicate knot values

    return NewPoints, NewKnots

if __name__ == "__main__":
    Points = np.array([[1., 1.], [2., 2.], [3., 2.], [4., 1.]])
    countPoints = np.size(Points, 0)
    oldOrder = 2
    Knots = OpenUniformKnotVector(oldOrder, countPoints, True)

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

    SplineOld = BSpline(Points, oldOrder, Knots, T)

    plt.plot(Points[:, 0], Points[:, 1], "x")
    plt.plot(SplineOld[:, 0], SplineOld[:, 1])

    plt.show()

    newOrder = 3

    NewPoints, NewKnots = RaiseOrderTwoToThree(Points, Knots)

    SplineNew = BSpline(NewPoints, newOrder, NewKnots, T)

    plt.plot(NewPoints[:, 0], NewPoints[:, 1], "x")
    plt.plot(SplineNew[:, 0], SplineNew[:, 1])

    plt.show()


import numpy as np
import scipy.stats as stats
from scipy.stats import f_oneway
from copy import copy
import warnings

from src.si.data import Dataset

class VarianceThreshold:

    def __init__(self, threshold=0):
        if threshold < 0:
            warnings.warn("The threshold is a non-negative value.")
        self.threshold = threshold

    def fit(self, dataset):
        X = dataset.X
        self._var = np.var(X, axis=0)  # axis=0 because columns

    def tansform(self, dataset, inline=False):
        X = dataset.X
        cond = self._var > self.threshold
        idxs = [i for i in range(len(cond)) if cond[i]]
        X_trans = X[:, idxs]
        xnames = [dataset.xnames[i] for i in idxs]
        if inline:
            dataset.X = X_trans
            dataset.xnames = xnames
            return dataset
        else:
            return Dataset(copy(X_trans), copy(dataset.Y), copy(xnames), copy(dataset.yname))

    def fit_transform(self, dataset, inline=False):
        self.fit(dataset)
        return self.tansform(dataset, inline=inline)

class SelectKBest:
    def __init__(self, k, score_function="f_regression"):
        available_sf = ["f_classif", "f_regression"]

        if score_function not in available_sf:
            raise Exception(f"Scoring function not available. Please choose between: {available_sf}.")
        elif score_function == "f_classif":
            self.function = f_classif
        else:
            self.function = f_regression

        if k <= 0:
            raise Exception("The K value must be higher than 0.")
        else:
            self.k = k

    def fit(self, dataset):
        self.F_stat, self.pvalue = self.function(dataset)

    def transform(self, dataset, inline=False):
        X, Xnames = dataset.X, dataset.xnames

        if self.k > X.shape[1]:
            warnings.warn("The K value provided is greater than the number of features."
                          f"All {X.shape[1]} features will be selected")
            self.k = int(X.shape[1])

        sel_feats = np.argsort(self.F_stat)[-self.k:]  # lista de features selecionadas ordenada pelo F_stat
        # sel_feats = np.sort(sel_feats)  # caso queira apresentar as features pela ordem de aparecimento no dataset

        x = X[:, sel_feats]  # dados correspondentes as features selecionadas
        x_names = [Xnames[index] for index in sel_feats]

        if inline:
            dataset.X = x
            dataset.xnames = x_names
            return dataset
        else:
            return Dataset(x, copy(dataset.Y), x_names, copy(dataset.yname))

    def fit_transform(self, dataset, inline=False):
        self.fit(dataset)
        return self.transform(dataset, inline=inline)

def f_classif(dataset):
    X, y = dataset.getXy()
    args = []
    for k in np.unique(y):
        args.append(X[y == k, :])
    F_stat, pvalue = f_oneway(*args)
    return F_stat, pvalue

def f_regression(dataset):
    X, y = dataset.getXy()
    cor_coef = np.array([stats.pearsonr(X[:, i], y)[0] for i in range(X.shape[1])])
    dof = y.size - 2  # degrees of freedom
    cor_coef_sqrd = cor_coef ** 2
    F = cor_coef_sqrd / (1 - cor_coef_sqrd) * dof
    p = stats.f.sf(F, 1, dof)
    return F, p


"""Python functions that solve PDEs."""
import numpy as np

def HeatEqn_FT(D, L, x, t, u_0):
    """
    Solve the 1-D Heat equation using the Fourier Transform.

    For periodic boundary conditions

    Arguments:
        inputs:
        D -- diffusion coefficient
        L -- length of spatial domain, the domain will be [-L/2, L/2)
        x -- 1D numpy array with spatial discretization
        t -- 1D numpy array with time discretization
        u_0 -- 1D numpy array with initial condition
        outputs:
        U -- 2D numpy array with solution to Heat equation, shape is
            (number of time steps, number of spatial points)
    """
    n = x.size
    k = (2 * np.pi / L) * np.fft.fftfreq(n, d=1 / n)
    u_0t = np.fft.fft(u_0)

    U = np.zeros((t.size, x.size))
    for ti in range(t.size):
        U[ti, :] = np.fft.ifft(np.exp(-D * k**2 * t[ti]) * u_0t)

    return U

def Burgers_Periodic(mu, eps, x, t_output, dt_factor, u_k):
    """Solve Burgers' equation.

    Burgers' equation:
        u_t + eps*u*u_x = mu*u_xx

    Solve using a second order FD method
    For periodic boundary conditions

    Arguments:
        inputs:
        mu -- diffusion coeffient/ viscosity
        eps -- strength of advection
        x -- 1D numpy array with spatial discretization
        t_output -- 1D numpy array with time discretization
        dt_factor -- divide dt from the above time discretization when solving
            (i.e. refine the time step for numerical stability,
            but only output every dt_factor steps)
        u_k -- 1D numpy array with initial condition
        outputs:
        U -- 2D numpy array with solution to Burgers' equation, shape is
            (number of time steps, number of spatial points)
    """
    n = x.size
    dx = x[1] - x[0]
    dt = (t_output[1] - t_output[0]) / dt_factor
    nt = (t_output.size - 1) * dt_factor + 1

    # Solve with FD scheme
    U = np.zeros((t_output.size, n))
    U[0, :] = u_k
    plus_ind = np.arange(1, n + 1) % n
    minus_ind = np.arange(-1, n - 1) % n
    for ti in range(1, nt):
        F_plus = (u_k**2 + u_k[plus_ind]**2) / 4
        F_minus = (u_k**2 + u_k[minus_ind]**2) / 4
        u_k = (u_k + dt *
               (mu * (u_k[plus_ind] - 2 * u_k + u_k[minus_ind])
                / dx**2 - eps * (F_plus - F_minus) / dx))

        if ti % dt_factor == 0:
            U[ti // dt_factor, :] = u_k

    return U

def KS_Periodic(x, tmax, ntime, u):
    """Solve the Kuramoto-Sivashinsky equation.

    Kuramoto-Sivashinsky equation:
        u_t = -u*u_x - u_xx - u_xxxx

    Solve in Fourier space using ETDRK4 time-stepping
        (See Kassam and Trefethen, 2005)
    For periodic boundary conditions

    Arguments:
        inputs:
        x -- 1D numpy array with spatial discretization
        tmax -- end time for simulation
        ntime -- number of time steps
        u -- 1D numpy array with initial condition
        outputs:
        U -- 2D numpy array with solution to KS equation, shape is
            (number of time steps, number of spatial points)
    """
    N = x.size
    v = np.fft.fft(u)

    # Precompute various ETDRK4 scalar quantities:
    h = 0.025
    k = (2 * np.pi / (x[-1] - 2 * x[0] + x[1])) * np.fft.fftfreq(N, d=1 / N)
    L = k**2 - k**4
    E = np.exp(h * L)
    E2 = np.exp(h * L / 2)
    M = 64
    r = np.exp(1j * np.pi * (np.arange(1, M + 1) - .5) / M)
    LR = h * np.tile(np.reshape(L, (N, 1)), (1, M)) + np.tile(r, (N, 1))
    Q = h * np.real(np.mean((np.exp(LR / 2) - 1) / LR, axis=1))
    f1 = h * np.real(np.mean(
        (-4 - LR + np.exp(LR) * (4 - 3 * LR + LR**2)) / LR**3, axis=1))
    f2 = h * np.real(np.mean(
        (2 + LR + np.exp(LR) * (-2 + LR)) / LR**3, axis=1))
    f3 = h * np.real(np.mean(
        (-4 - 3 * LR - LR**2 + np.exp(LR) * (4 - LR)) / LR**3, axis=1))

    # Main time-stepping loop:
    uu = u
    nmax = int(np.round(tmax / h))
    nplt = int(np.floor((tmax / (ntime - 1)) / h))
    g = -0.5j * k
    for n in range(nmax):
        Nv = g * np.fft.fft(np.real(np.fft.ifft(v))**2)
        a = E2 * v + Q * Nv
        Na = g * np.fft.fft(np.real(np.fft.ifft(a))**2)
        b = E2 * v + Q * Na
        Nb = g * np.fft.fft(np.real(np.fft.ifft(b))**2)
        c = E2 * a + Q * (2 * Nb - Nv)
        Nc = g * np.fft.fft(np.real(np.fft.ifft(c))**2)
        v = E * v + Nv * f1 + 2 * (Na + Nb) * f2 + Nc * f3
        if np.mod(n + 1, nplt) == 0:
            u = np.real(np.fft.ifft(v))
            uu = np.vstack((uu, u))

    return uu


import numpy as np
from scipy import ndimage

#
# GETWEIGHTMAP: compute the wieght map for data set
#
# @param masks
# @param w0
# @param sigma
#
# @Ref: https://arxiv.org/pdf/1505.04597.pdf
#       https://www.kaggle.com/piotrczapla/tensorflow-u-net-starter-lb-0-34/notebook
#
# Ecuation 2
#
# w(x) = w_c(x) + w_0*\exp(-\frac{(d_1(x)-d_2(x))^2}{2\sigma^2})
#
# where w_c : Ω → R is the weight map to balance the class frequencies,
# d_1 : Ω → R denotes the distance to the border of the nearest cell and
# d_2 : Ω → R the distance to the border of the second nearest cell.
# In our experiments we set w0 = 10 and σ ≈ 5 pixels.
#
#
#

def getunetweightmap( merged_mask, masks, w0=10, sigma=5, ):

    # WxHxN to NxWxH
    #masks = masks.transpose( (2,0,1) )

    weight = np.zeros(merged_mask.shape)
    # calculate weight for important pixels
    distances = np.array([ndimage.distance_transform_edt(m==0) for m in masks])
    shortest_dist = np.sort(distances, axis=0)
    # distance to the border of the nearest cell
    d1 = shortest_dist[0]
    # distance to the border of the second nearest cell
    d2 = shortest_dist[1] if len(shortest_dist) > 1 else np.zeros(d1.shape)

    w_b = np.exp(-(d1+d2)**2/(2*sigma**2)).astype(np.float32)
    w_c = getweightmap(merged_mask)
    w = w_c + w0*w_b

    #weight = 1 + (merged_mask == 0) * w
    weight = 1 + w

    return weight

#weight map
def getweightmap(mask):

    w_c = np.empty(mask.shape)
    classes = np.unique(mask)
    frecs = [ np.sum(mask == i)/float(mask.size) for i in classes ]

    # Calculate
    n = len(classes)
    for i in range( n ):
        w_c[mask == i] = 1 / (n*frecs[i])

    return w_c


# -*- coding: utf-8 -*-
"""
Spyder Editor

This is a temporary script file.
"""

import numpy as np
#import matplotlib.pyplot as plt

def loadDataSet(data_dir):
    dataMat = np.zeros((0,5))
    labelMat =np.zeros((0,1))
    fr = open(data_dir)
    for line in fr.readlines():
        lineArr = line.strip().split(',')
        dataMat=np.append(dataMat,[[1.0,float(lineArr[0]), float(lineArr[1]),float(lineArr[2]),float(lineArr[3])]],0)
        labelMat=np.append(labelMat,[[int(lineArr[4])]],0)
    return dataMat, labelMat

def sigmoid(x):
    return 1.0/(1+np.exp(-x)) #定义sigmoid函数

def grad_desc(dataMat,labelMat):
    m,n = np.shape(dataMat)
    a=0.001
    times=40
    weight = np.ones((n,1))
    for i in range(times):
        h= sigmoid(np.dot(dataMat,weight))
        error = h-labelMat
        weight = weight-a*np.dot(dataMat.T,error)
    return weight

def  random_grad_desc(dataMat,labelMat):
    a=0.001
    times = 90
    m,n = np.shape(dataMat)
    weight=np.ones((n,1))
    for i in range(times):
        for j in range(m):
            h=sigmoid(sum(np.dot(dataMat[j,:],weight)))
            error=h-labelMat[j]
            weight = weight-a*dataMat[j,:]*error
    return weight

def LR_classify(x,weight):
    prob = sigmoid(sum(np.dot(x,weight)))
    if prob > 0.5:
        return 1
    else:
        return 0

def LR_test(dataMat,labelMat,weight):
    errorCount = 0
    numTest = 0
    for i in range(dataMat.shape[0]):
        numTest += 1
        if LR_classify(dataMat[i,:],weight) != labelMat[i]:
            errorCount += 1
    errorRate = (float(errorCount)/numTest)
    return errorRate

if __name__ == '__main__':
    data_dir='data_banknote_authentication.txt'
    dataMat, labelMat = loadDataSet(data_dir)
    #print(dataMat, labelMat)
    #dataMat=np.array(dataMat)
    #labelMat=np.array(labelMat)
    dataMat_train = dataMat[0:int(.8*dataMat.shape[0]),:]
    dataMat_test = dataMat[int(.8*dataMat.shape[0]):,:]
    labelMat_train = labelMat[0:int(.8*labelMat.shape[0])]
    labelMat_test = labelMat[int(.8*labelMat.shape[0]):]

    weights=grad_desc(dataMat_train,labelMat_train)
##    weights=random_grad_desc(dataMat_train,labelMat_train)
    errorRate=LR_test(dataMat_test,labelMat_test,weights)
    print ("the error rate of this test is :",errorRate)


"""Tests for Function class"""

import unittest

import sympy as sym

from fractpy import Function

x = sym.Symbol("x")

class TestFunction(unittest.TestCase):
    """Tests for the class Function."""

    def test_function_init(self):
        # Test for a valid function
        func = "(x**2 + 1)(x - 1)"
        a = Function(func)
        self.assertEqual(a.function, (x ** 2 + 1) * (x - 1))

        # Test for an invalid function
        func = "x + y"
        with self.assertRaises(TypeError) as mess:
            a = Function(func)
        err = mess.exception
        self.assertEqual(
            "x + y is not a single variable function, it has 2 variables",
            str(err),
        )

    def test_function_repr(self):
        func = "x**2 + x - 4"
        a = Function(func)
        self.assertEqual(a.__repr__(), "x**2 + x - 4")

    def test_roots(self):
        func = "(x + 1)(x - I)(x + I)"
        a = Function(func)
        self.assertEqual(set(a.roots()), set([-1, 1j, -1j]))

    def test_differentiate(self):
        func = "x**4 - 2*x**2 - 4"
        a = Function(func)
        derivative = 4 * x ** 3 - 4 * x
        self.assertEqual(a.differentiate(), derivative)

    def test_relative_difference(self):
        func = "4*x**2 - x"
        a = Function(func)
        rd = (4 * x ** 2 - x) / (8 * x - 1)
        self.assertEqual(a._relative_difference(), rd)

    def test_make_python_function(self):
        func = "x**2 + 1"
        a = Function(func)
        func_0 = a._make_python_function()

        f = x ** 2 + 1
        func_1 = Function("x")._make_python_function(f, x)

        def func_2(x):
            return x ** 2 + 1

        # Check if all functions are equal
        ans_0, ans_1, ans_2 = [], [], []
        for i in range(5):
            ans_0.append(func_0(i))
            ans_1.append(func_1(i))
            ans_2.append(func_2(i))
        self.assertEqual(ans_0, ans_1)
        self.assertEqual(ans_1, ans_2)

    def test_rd_python_function(self):
        func = "x**3 - 2x + 1"
        a = Function(func)
        func_0 = a._rd_python_function()

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

        ans_0, ans_1 = [], []
        for i in range(5):
            ans_0.append(func_0(i))
            ans_1.append(func_1(i))
        self.assertEqual(ans_0, ans_1)


# -*- coding:UTF8 -*-
import numpy as np
import os,sys
import argparse
from tools import loadData
from tools import ulti
from LUFactorization import LU_factorization
from SchmidtProcedure import Schmidt_procedure
from HouseholderReduction import Housholder_reduction
from GivensReduction import Givens_reduction

# 获取当前工作路径
path = os.getcwd()

ap = argparse.ArgumentParser(description="Four Reduction Methods")
#选择使用的约简模型，四个选项'LU','QR','HR','GR'，其中LU代表LU factorization, QR代表Schmidt Procedure, HR代表Housholder Reduction, GR代表Givens Reduction!
ap.add_argument("--model", type=str, choices=['LU','QR','HR','GR'], default="LU",
                help="4 choices in ['LU','QR','HR','GR'], LU->LU factorization, QR->Schmidt Procedure, HR->Housholder Reduction, GR->Givens Reduction!")

ap.add_argument("--input", type=str, default="data/example1.txt",
                help="input example file path.")
# ap.add_argument("--egnum", type=int, default=1,
#                 help="number of examples to test!")

args = ap.parse_args()

if __name__ == "__main__":
    input_file=path+'/'+args.input
    # print(input_file)
    matrix, m, n= loadData.load_array(input_file, args.model)
    if matrix.size ==0:
        print("input Error!")
        sys.exit()

    if args.model == "LU":
        print("\nBe careful you have selected LU Factorization, the input should be a square matrix.\n")
    elif args.model == "QR":
        # 首先判断矩阵是否是列线性无关的
        mat_rank = ulti.rank_of_matrix(matrix,m,n)
        if mat_rank<n:
            print("Error!\nThe matrix with linearly dependent columns Can Not be uniquely factored as A=QR!\n\n")
            sys.exit()

    print("="*50,"\norigin matrix type: {m} * {n}" .format(m=m,n=n),"\nOrigin Matrix A = ")
    ulti.print_array(matrix, m, n)
    print("="*50, "\nProcessing:")
    if args.model == "LU":
        L,U,P = LU_factorization(matrix, m, n)
        print("L=")
        ulti.print_array(L,m,m)
        print("U=")
        ulti.print_array(U,m,m)
        print("P=")
        ulti.print_array(P,m,m)
    elif args.model == "QR":
        Q,R = Schmidt_procedure(matrix,m,n)
        print("Q=")
        ulti.print_array(Q,m,n)
        print("R=")
        ulti.print_array(R,n,n)
    elif args.model == "HR":
        Q,R = Housholder_reduction(matrix,m,n)
        print("Q=")
        ulti.print_array(Q,m,m)
        print("R=")
        ulti.print_array(R,m,n)
    elif args.model=="GR":
        Q,R = Givens_reduction(matrix,m,n)
        print("Q=")
        ulti.print_array(Q,m,m)
        print("R=")
        ulti.print_array(R,m,n)


import numpy as np
from scipy.sparse.linalg import LinearOperator, cg, gmres, lgmres

from cfdpy.derivative.finiteDifferenceMethods import centralFDM

class poisson2(object):
    def __init__(self, nx, ny, dx=1., dy=1.):
        self.nx = nx
        self.ny = ny
        self.dx = dx
        self.dy = dy
        self.p_shape = (self.ny, self.nx)
        self.A_shape = (self.nx*self.ny, self.nx*self.ny)
        self.derivative = centralFDM(order=6, highestDerivative=2)
        self.exitCode = 0
        self.A = LinearOperator(self.A_shape, matvec=self.lhs)

    def lhs(self, p_flatten):
        p = np.reshape(p_flatten, self.p_shape)
        p = ( self.derivative(p, h=self.dx, axis=-1, derivative=2)
            + self.derivative(p, h=self.dy, axis=-2, derivative=2))
        return p.flatten()

    def rhs(self, u, v):
        return ( self.derivative(u, h=self.dx, axis=-1)
               + self.derivative(v, h=self.dy, axis=-2)).flatten()

    def solve(self, u, v, method="gmres"):
        if method=="gmres":
            p_flatten, self.exitCode = gmres(A=self.A, b=self.rhs(u, v))
        elif method=="cg":
            p_flatten, self.exitCode = cg(A=self.A, b=self.rhs(u, v))
        elif method=="lgmres":
            p_flatten, self.exitCode = lgmres(A=self.A, b=self.rhs(u, v))
        else:
            p_flatten = np.linalg.solve(self.A(np.identity(self.nx*self.ny)), self.rhs(u, v))
        return np.reshape(p_flatten, self.p_shape)


import numpy as np
from random import Random

def fitness(population, n):

    #index_fit = 0
    population_fit = []
    flag = False
    for i in range(len(population)):
      chromosome = []
      if (len(population) != n):
        chromosome.append(population[i])
      else:
        chromosome = population
        flag = True

      horizontal_clash = abs(len(chromosome) - len(np.unique(chromosome)))
      diagonal_clashes = 0
      # calculate diagonal clashes
      for i in range(len(chromosome)):
          for j in range(i,len(chromosome)):
              if ( i != j):
                  dx = abs(i-j)
                  dy = abs(chromosome[i] - chromosome[j])
                  if(dx == dy):
                      diagonal_clashes += 1

      fit = 28 - (horizontal_clash + diagonal_clashes)
      population_fit.append(fit)
      if (flag):
        return population_fit
      #index_fit += 1
    return population_fit

def select(population, fit):

    temp = population
    a = []
    for i in range(len(temp)):
      a.append(i)
    size = 1
    fit_lst = fit
    p = []
    for i in range(len(fit_lst)):
      t2 = 0.0
      t1 = float(fit_lst[i])
      for j in range(len(fit_lst)):
        t2 += fit_lst[j]
      p.append(t1/t2)

    #p = [.31, .29, 0.26, 0.14]

    index_num = np.random.choice(a, size, True, p)
    rand_select = temp[int(index_num)]
    return rand_select

def crossover(x, y):

    r = Random()
    idx = r.randint(3,5)
    x = x[0:idx]
    y = y[idx:8]
    #child = x + y
    #child = x[0:idx] + y[idx:8]
    child = np.concatenate((x , y))
    return child
    #return x[0:idx] + y[idx:8]

def mutate(child):

    r = Random()
    idx = r.randint(0, 7) #random index
    child[idx] = r.randint(1,8) #replaces selected random index with a random integer

    return child

def GA(population, n, mutation_threshold = 0.3):

    gen_max = 100000
    gen_counter = gen_max
    target_fitness = 28
    while gen_counter > 0:
      new_population = []
      for i in range(len(population)):
        x = select(population, fitness(population, n))
        y = select(population, fitness(population, n))
        child = crossover(x, y)
        r = Random()
        if r.uniform(0, 1) < mutation_threshold:
          child = mutate(child)
        fit_child = fitness(child,n)
        if (fit_child[0] == target_fitness):
          print(child, " found in ", gen_max-gen_counter," generations\n")
          print("The max fitness value = ", fit_child)
          return child
        new_population.append(child)
      population = new_population
      gen_counter -= 1
    print("nothing found in ", gen_max, " genrations\n")
    return None

'''for 8 queen problem, n = 8'''
n = 8

'''start_population denotes how many individuals/chromosomes are there
  in the initial population n = 8'''
start_population = 10

'''if you want you can set mutation_threshold to a higher value,
   to increase the chances of mutation'''
mutation_threshold = 0.3

'''creating the population with random integers between 0 to 7 inclusive
   for n = 8 queen problem'''
population = np.random.randint(0, n, (start_population, n))

'''calling the GA function'''
GA(population, n, mutation_threshold)


import numpy as np
import numpy.linalg as la
from io import StringIO

#def print_mat(stream, mat):
def print_mat(mat):

    stream = StringIO()
    np.savetxt(stream, mat, fmt="%.3f")
    print( stream.getvalue() )

# -----------------------------------

# transition matrix L
L = np.array([
    [0,   1/2, 1/3, 0, 0,   0   ],
    [1/3, 0,   0,   0, 1/2, 0   ],
    [1/3, 1/2, 0,   1, 0,   1/2 ],
    [1/3, 0,   1/3, 0, 1/2, 1/2 ],
    [0,   0,   0,   0, 0,   0   ],
    [0,   0,   1/3, 0, 0,   0   ]
])

# output transition matrix
print_mat(mat=L)

#  compute eigenvalue and eigenvector
e_val, e_vacs = la.eig(L)

# take the eigenvector with eigenvalue = 1
vec = np.transpose(e_vacs)[0]

#  take only real part
vec_real = vec.real
vec_real = vec_real * 100.0/sum(vec_real)

# output eigenvector
print_mat(mat=vec_real)


#!/usr/bin/env python
# -*- encoding: utf-8 -*-
"""
Topic: 矩阵和线性代数
Desc :
"""
import numpy as np
import numpy.linalg

def matrix_linear():
    m = np.matrix([[1,-2,3],[0,4,5],[7,8,-9]])
    print(m)

    # Return transpose  转置矩阵
    print(m.T)

    # Return inverse  # 逆矩阵
    print(m.I)

    # Create a vector and multiply
    v = np.matrix([[2],[3],[4]])
    print(v)
    print(m * v)

    # Determinant 行列式
    print(numpy.linalg.det(m))

    # Eigenvalues 特征值
    print(numpy.linalg.eigvals(m))

    # Solve for x in m*x = v
    x = numpy.linalg.solve(m, v)
    print(x)
    print(m * x)
    print(v)

if __name__ == '__main__':
    matrix_linear()


import numpy as np
import math

def normalize(v):
    m = np.linalg.norm(v)
    if m == 0:
        return v
    return v / m

def translate(xyz):
    x, y, z = xyz[:3]
    return np.matrix([[1,0,0,x],
                      [0,1,0,y],
                      [0,0,1,z],
                      [0,0,0,1]], dtype=np.float32)

def scale(xyz):
    x, y, z = xyz[:3]
    return np.matrix([[x,0,0,0],
                      [0,y,0,0],
                      [0,0,z,0],
                      [0,0,0,1]], dtype=np.float32)

def rotate(a, xyz):
    x, y, z = normalize(xyz)
    a = math.radians(a)
    s = math.sin(a)
    c = math.cos(a)
    nc = 1 - c
    return np.matrix([[x*x*nc +   c, x*y*nc - z*s, x*z*nc + y*s, 0],
                      [y*x*nc + z*s, y*y*nc +   c, y*z*nc - x*s, 0],
                      [x*z*nc - y*s, y*z*nc + x*s, z*z*nc +   c, 0],
                      [           0,            0,            0, 1]], dtype=np.float32)

def rotate_x(a):
    a = math.radians(a)
    s = math.sin(a)
    c = math.cos(a)
    return np.matrix([[1,0,0,0],
                      [0,c,-s,0],
                      [0,s,c,0],
                      [0,0,0,1]],  dtype=np.float32)

def rotate_y(a):
    a = math.radians(a)
    s = math.sin(a)
    c = math.cos(a)
    return np.matrix([[c,0,s,0],
                      [0,1,0,0],
                      [-s,0,c,0],
                      [0,0,0,1]], dtype=np.float32)

def rotate_z(a):
    a = math.radians(a)
    s = math.sin(a)
    c = math.cos(a)
    return np.matrix([[c,-s,0,0],
                      [s,c,0,0],
                      [0,0,1,0],
                      [0,0,0,1]], dtype=np.float32)

def look_at(eye, center, up=[0, 1, 0]):
    eye = np.array(eye, dtype=np.float32).flatten()[:3]
    center = np.array(center, dtype=np.float32).flatten()[:3]
    up = np.array(up, dtype=np.float32).flatten()[:3]

    f = normalize(center - eye)
    s = normalize(np.cross(f, up))
    u = np.cross(s, f)

    M = np.matrix(np.identity(4), dtype=np.float32)
    M[:3,:3] = np.vstack([s, u, -f])
    M[0, 3] = -np.dot(s, eye)
    M[1, 3] = -np.dot(u, eye)
    M[2, 3] =  np.dot(f, eye)
    return M


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

#Import dataset
dataset = pd.read_csv('Mall_Customers.csv')
X = dataset.iloc[:, [3, 4]].values

#Using the dendrogram
import scipy.cluster.hierarchy as sch
dendogram = sch.dendrogram(sch.linkage(X, method = 'ward'))
plt.title('Dendrogram')
plt.xlabel('Customers')
plt.ylabel('Euclidean distances')
plt.show()

#Choosing right k cluster
from sklearn.cluster import AgglomerativeClustering
hc = AgglomerativeClustering(n_clusters = 5, affinity = 'euclidean', linkage = 'ward')
y_pred = hc.fit_predict(X)

#Visualizing the results
plt.scatter(X[y_pred == 0, 0], X[y_pred == 0, 1], s = 100, c = 'red', label = 'Careful')
plt.scatter(X[y_pred == 1, 0], X[y_pred == 1, 1], s = 100, c = 'blue', label = 'Standard')
plt.scatter(X[y_pred == 2, 0], X[y_pred == 2, 1], s = 100, c = 'green', label = 'Target')
plt.scatter(X[y_pred == 3, 0], X[y_pred == 3, 1], s = 100, c = 'cyan', label = 'Careless')
plt.scatter(X[y_pred == 4, 0], X[y_pred == 4, 1], s = 100, c = 'magenta', label = 'Sensible')
plt.xlabel('Annual Income')
plt.ylabel('Spending Score (1-100)')
plt.legend()
plt.show()

Master Machine Learning A-Z (Udemy)/Machine Learning A-Z/Part 4 - Clustering/Section 25 - Hierarchical Clustering/Lesson16.py


import math
import numpy as np
#import cupy as np

activation_functiones = {
    'sigmoid': lambda x : math.exp(-np.logaddexp(0, -x)),
    'tanh' : lambda x : np.tanh(x)
}

class Network():
    def __init__(self,input_size,hidden_layers):
        self.input_size = input_size
        self.layers = hidden_layers

    def feed_forward(self,data):
        if self.input_size != len(data):
            raise ValueError("Wrong data size {} {}".format(self.input_size,len(data)))
        for layer in self.layers:
            data = layer.feed_forward(data)

        return data

    def train(self,input_data,input_labels):
        accuracy = 0
        average_cost = 0
        for image, label in zip(input_data,input_labels):
            output = self.feed_forward(image)
            cost = self._cost_function(output,self._generate_one_hot(label))
            average_cost += cost
            if np.argmax(output) == label:
                accuracy +=1

        return average_cost

    def _cost_function(self,input,desired_input):
        return np.sum(np.power(input-desired_input,2))

    def _generate_one_hot(self,input):
        one_hot = np.zeros(10)
        one_hot[input] = 1
        return one_hot

class Layer():
    def __init__(self,size,input_size,activation_function='sigmoid'):
        self.weights = np.random.rand(input_size,size)*0.01
        self.biases = np.zeros(shape=(size))
        self.activation_function = np.vectorize(activation_functiones[activation_function])

    def feed_forward(self,input):
        return self.activation_function(np.add(np.dot(input, self.weights),self.biases))


import numpy as np

def sigmf(x, params):
    if not isinstance(params, list):
        raise TypeError("Params should be a list with two values.")
    if len(params) != 2:
        raise TypeError("Number of parameters are incorrect. Expected 2 values in the list.")
    if not (isinstance(params[0], float) and isinstance(params[1], float)):
        raise TypeError("Parameters should be in float.")

    a = params[0] # Controls width of the sigmoid region
    c = params[1] # Offset or bias. This is the center value of the sigmoid
    return 1/(1 + np.exp(-a*(x - c)))


'''
ANKIT KHANDELWAL
15863
Exercise 6
'''

import numpy as np
import pandas as pd

pitch = pd.read_csv("pitch.txt", sep='\t', header=None)
n1 = len(pitch)
pitch_array = np.zeros(n1)
for i in range(n1):
    pitch_array[i] = pitch[0][i]

def FFT(x):
    N = len(x)
    if N == 1:
        return x
    X_even = FFT(x[::2])
    X_odd = FFT(x[1::2])
    factor = np.exp(-2j * np.pi * np.arange(N) / N)
    return np.concatenate([X_even + factor[:N // 2] * X_odd, X_even + factor[N // 2:] * X_odd])

c = FFT(pitch_array)
c1 = np.fft.fft(pitch_array)
print(c, 'Using user defined function.\n')
print(c1, 'Using built-in function.\n')

diff = abs(c - c1)
max_error = max(diff)
print(max_error, 'This is the max error between the two.')

Ankit Khandelwal_HW4/Exercise 6/exercise 6.py


import numpy as np

from prml.linear._classifier import Classifier

class LogisticRegression(Classifier):
    """Logistic regression model.

    y = sigmoid(X @ w)
    t ~ Bernoulli(t|y)
    """

    @staticmethod
    def _sigmoid(a):
        return np.tanh(a * 0.5) * 0.5 + 0.5

    def fit(
        self,
        x_train: np.ndarray,
        y_train: np.ndarray,
        max_iter: int = 100,
    ):
        """Maximum likelihood estimation of logistic regression model.

        Parameters
        ----------
        x_train : (N, D) np.ndarray
            training data independent variable
        y_train : (N,) np.ndarray
            training data dependent variable
            binary 0 or 1
        max_iter : int, optional
            maximum number of parameter update iteration (the default is 100)
        """
        w = np.zeros(np.size(x_train, 1))
        for _ in range(max_iter):
            w_prev = np.copy(w)
            y = self._sigmoid(x_train @ w)
            grad = x_train.T @ (y - y_train)
            hessian = (x_train.T * y * (1 - y)) @ x_train
            try:
                w -= np.linalg.solve(hessian, grad)
            except np.linalg.LinAlgError:
                break
            if np.allclose(w, w_prev):
                break
        self.w = w

    def proba(self, x: np.ndarray):
        """Return probability of input belonging class 1.

        Parameters
        ----------
        x : (N, D) np.ndarray
            Input independent variable

        Returns
        -------
        (N,) np.ndarray
            probability of positive
        """
        return self._sigmoid(x @ self.w)

    def classify(self, x: np.ndarray, threshold: float = 0.5):
        """Classify input data.

        Parameters
        ----------
        x : (N, D) np.ndarray
            Input independent variable to be classified
        threshold : float, optional
            threshold of binary classification (default is 0.5)

        Returns
        -------
        (N,) np.ndarray
            binary class for each input
        """
        return (self.proba(x) > threshold).astype(int)


import numpy as np
from scipy.stats import zscore

def similarity(X, Y, method):
    '''
    SIMILARITY Computes similarity matrices

    Usage:
        sim = similarity(X, Y, method)

    Input:
    X   N1 x M matrix
    Y   N2 x M matrix
    method   string defining one of the following similarity measure
           'SMC', 'smc'             : Simple Matching Coefficient
           'Jaccard', 'jac'         : Jaccard coefficient
           'ExtendedJaccard', 'ext' : The Extended Jaccard coefficient
           'Cosine', 'cos'          : Cosine Similarity
           'Correlation', 'cor'     : Correlation coefficient

    Output:
    sim Estimated similarity matrix between X and Y
        If input is not binary, SMC and Jaccard will make each
        attribute binary according to x>median(x)

    Copyright, Morten Morup and Mikkel N. Schmidt
    Technical University of Denmark '''

    X = np.mat(X)
    Y = np.mat(Y)
    N1, M = np.shape(X)
    N2, M = np.shape(Y)

    method = method[:3].lower()
    if method=='smc': # SMC
        X,Y = binarize(X,Y);
        sim = ((X*Y.T)+((1-X)*(1-Y).T))/M
    elif method=='jac': # Jaccard
        X,Y = binarize(X,Y);
        sim = (X*Y.T)/(M-(1-X)*(1-Y).T)
    elif method=='ext': # Extended Jaccard
        XYt = X*Y.T
        sim = XYt / (np.log( np.exp(sum(np.power(X.T,2))).T * np.exp(sum(np.power(Y.T,2))) ) - XYt)
    elif method=='cos': # Cosine
        sim = (X*Y.T)/(np.sqrt(sum(np.power(X.T,2))).T * np.sqrt(sum(np.power(Y.T,2))))
    elif method=='cor': # Correlation
        X_ = zscore(X,axis=1,ddof=1)
        Y_ = zscore(Y,axis=1,ddof=1)
        sim = (X_*Y_.T)/(M-1)
    return sim

def binarize(X,Y=None):
    ''' Force binary representation of the matrix, according to X>median(X) '''
    x_was_transposed = False
    if Y is None:
        if X.shape[0] == 1:
            x_was_transposed = True
            X = X.T;

        Xmedians = np.ones((np.shape(X)[0],1)) * np.median(X,0)
        Xflags = X>Xmedians
        X[Xflags] = 1; X[~Xflags] = 0

        if x_was_transposed:
            return X.T
        return X
    else:
        #X = np.matrix(X); Y = np.matrix(Y);
        #XYmedian= np.median(np.bmat('X; Y'),0)
        #Xmedians = np.ones((np.shape(X)[0],1)) * XYmedian
        #Xflags = X>Xmedians
        #X[Xflags] = 1; X[~Xflags] = 0
        #Ymedians = np.ones((np.shape(Y)[0],1)) * XYmedian
        #Yflags = Y>Ymedians
        #Y[Yflags] = 1; Y[~Yflags] = 0
        return [binarize(X,None),binarize(Y,None)]

## Example
#import numpy as np
#from similarity import binarize2
#A = np.asarray([[1,2,3,4,5],[6,7,8,9,10],[1,2,3,4,5],[6,7,8,9,10]]).T
#binarize2(A,['a','b','c','d'])
def binarize2(X,columnnames):
    X = np.concatenate((binarize(X),1-binarize(X)),axis=1)

    new_column_names = []
    [new_column_names.append(elm) for elm in [name+' 50th-100th percentile' for name in columnnames]]
    [new_column_names.append(elm) for elm in [name+' 0th-50th percentile' for name in columnnames]]

    return X, new_column_names


import pandas as pd
import numpy as np
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
from sklearn.linear_model import LogisticRegression
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis as LDA
from sklearn.datasets import make_moons
from sklearn.datasets import make_circles
from sklearn.decomposition import KernelPCA
from scipy.spatial.distance import pdist, squareform
from scipy import exp
from scipy.linalg import eigh
from matplotlib.ticker import FormatStrFormatter
from plot_decision_regions import *
from rbf_kernel_pca import *

# for sklearn 0.18's alternative syntax
from distutils.version import LooseVersion as Version
from sklearn import __version__ as sklearn_version
if Version(sklearn_version) < '0.18':
    from sklearn.grid_search import train_test_split
    from sklearn.lda import LDA
else:
    from sklearn.model_selection import train_test_split
    from sklearn.discriminant_analysis import LinearDiscriminantAnalysis as LDA

#############################################################################
print(50 * '=')
print('Section: Example 2: Separating concentric circles')
print(50 * '-')

X, y = make_circles(n_samples=1000, random_state=123, noise=0.1, factor=0.2)

plt.scatter(X[y == 0, 0], X[y == 0, 1], color='red', marker='^', alpha=0.5)
plt.scatter(X[y == 1, 0], X[y == 1, 1], color='blue', marker='o', alpha=0.5)

# plt.tight_layout()
# plt.savefig('./figures/circles_1.png', dpi=300)
plt.show()

# PCA
scikit_pca = PCA(n_components=2)
X_spca = scikit_pca.fit_transform(X)

fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(7, 3))

ax[0].scatter(X_spca[y == 0, 0], X_spca[y == 0, 1],
              color='red', marker='^', alpha=0.5)
ax[0].scatter(X_spca[y == 1, 0], X_spca[y == 1, 1],
              color='blue', marker='o', alpha=0.5)

ax[1].scatter(X_spca[y == 0, 0], np.zeros((500, 1)) + 0.02,
              color='red', marker='^', alpha=0.5)
ax[1].scatter(X_spca[y == 1, 0], np.zeros((500, 1)) - 0.02,
              color='blue', marker='o', alpha=0.5)

ax[0].set_xlabel('PC1')
ax[0].set_ylabel('PC2')
ax[1].set_ylim([-1, 1])
ax[1].set_yticks([])
ax[1].set_xlabel('PC1')

# plt.tight_layout()
# plt.savefig('./figures/circles_2.png', dpi=300)
plt.show()

# kernel PCA
X_kpca = rbf_kernel_pca(X, gamma=15, n_components=2)

fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(7, 3))
ax[0].scatter(X_kpca[y == 0, 0], X_kpca[y == 0, 1],
              color='red', marker='^', alpha=0.5)
ax[0].scatter(X_kpca[y == 1, 0], X_kpca[y == 1, 1],
              color='blue', marker='o', alpha=0.5)

ax[1].scatter(X_kpca[y == 0, 0], np.zeros((500, 1)) + 0.02,
              color='red', marker='^', alpha=0.5)
ax[1].scatter(X_kpca[y == 1, 0], np.zeros((500, 1)) - 0.02,
              color='blue', marker='o', alpha=0.5)

ax[0].set_xlabel('PC1')
ax[0].set_ylabel('PC2')
ax[1].set_ylim([-1, 1])
ax[1].set_yticks([])
ax[1].set_xlabel('PC1')

# plt.tight_layout()
# plt.savefig('./figures/circles_3.png', dpi=300)
plt.show()

# scikit-learn の KernelPCA で確認してみる
# 自前実装版と比べると、値のスケールが違う
scikit_kpca = KernelPCA(n_components=2, kernel='rbf', gamma=15)
X_skernpca = scikit_kpca.fit_transform(X)

plt.scatter(X_skernpca[y == 0, 0], X_skernpca[y == 0, 1],
            color='red', marker='^', alpha=0.5)
plt.scatter(X_skernpca[y == 1, 0], X_skernpca[y == 1, 1],
            color='blue', marker='o', alpha=0.5)
plt.xlabel('PC1')
plt.ylabel('PC2')
plt.show()


from __future__ import division
import doctest
import pylab as pl
import numpy as np
# a)	use newton's method to calculate roots
# 		equation = x^3 - x - 5
#		x_initial = 0.57735
#		max_iter = 50
#		print the results and explain them

## TODO : Write tests
# x^3 - 1 , re-written to get rid of powers
def f(x_r,x_i):
    '''
    >>> f(1,1)
    (-3.0, 2.0)
    >>> f(2,1)
    (1.0, 11.0)
    >>> f(1,0)
    (0.0, 0.0)
    '''
    z = complex(x_r, x_i)
    retVal = (z * z * z) - 1
    return retVal.real, retVal.imag

# 3 x^2 , re-written to get rid of powers
def f_dash(x_r, x_i):
    '''
    >>> f_dash(1,1)
    (0.0, 6.0)
    >>> f_dash(2,1)
    (9.0, 12.0)
    '''
    z = complex(x_r, x_i)
    retVal = 3 * z * z
    return retVal.real, retVal.imag

def get_next_appox(x_r, x_i):
    '''
    x_r : previous real value of x
    x_i : previous imag value of x
    '''
    xr = x_r
    xi = x_i
    x = complex(xr, xi)

    fx_tuple = f(xr, xi)
    fx = complex(fx_tuple[0], fx_tuple[1])

    fdashx_tuple = f_dash(xr, xi)
    fdashx = complex(fdashx_tuple[0], fdashx_tuple[1])

    retVal = x - (fx / fdashx)
    return retVal.real, retVal.imag

def get_magnitude(z):
    xr, xi = z
    return xr * xr + xi * xi

def run_newton_method(xr_init, xi_init, epsilon=10 ** (-12), max_iter=100):
    '''
    xr_init = initial real value of x
    xi_init = initial imag value of x
    '''
    xr_old = xr_init
    xi_old = xi_init
    xr_new, xi_new = get_next_appox(xr_init, xi_init)
    while(max_iter != 0):
        max_iter -= 1
        xr_old, xi_old = xr_new, xi_new
        xr_new, xi_new = get_next_appox(xr_old, xi_old)
        if abs(xr_old - xr_new) < epsilon and abs(xi_old - xi_new) < epsilon:
            break
        if f(xr_new, xi_new) < epsilon:
            break
    return xr_new, xi_new

def whichRoot(xr, xi):
    retVal = -1
    if xr < -0.4 and xr > -0.6 and xi  > -0.9 and xi < -0.7:
        retVal = 1
        # retVal = "r."
    elif (xr + -1 < .01 and xi < .01):
        retVal = 2
        # retVal = "g."
    elif (xr > -0.6 and xr < -0.4) and (xi > 0.8 and xi < 0.9):
        retVal = 3
        # retVal = "b."
    return retVal

if __name__ == '__main__':
    doctest.testmod()

    x_real_nums = np.linspace(-1, 1, 1000)
    x_imag_nums = np.linspace(-1, 1, 1000)

    outputs = []

    for xr in x_real_nums:
        outputs.append([])
        for xi in x_imag_nums:
            fx_r, fx_i = run_newton_method(xr, xi)
            outputs[-1].append(whichRoot(fx_r,fx_i))
    pl.figure(1)
    pl.pcolor(np.array(outputs, np.float))
    pl.draw()
    pl.savefig("figure_q3_test.pdf")
    pl.show()


"""
Calculate mean and Gaussian curvatures of a surface given by z=f(x, y)
"""
import sympy

def getcurvatureexpr(expr, symmap=None):
    """
    Given an expression f(x, y), calculate symbolic expressions for Gaussian
    and mean curvatures i.e. K and H respectively.
    """
    locals().update(symmap)
    x, y = sympy.symbols('x, y')
    z = eval(expr)

    p = sympy.Matrix([x, y, z])
    px = p.diff(x)
    py = p.diff(y)
    n = px.cross(py)/px.cross(py).norm()

    E = px.dot(px)
    F = px.dot(py)
    G = py.dot(py)

    L = px.diff(x).dot(n)
    M = px.diff(y).dot(n)
    N = py.diff(y).dot(n)

    denominator = E*G - F**2
    K = (L*N - M**2)/denominator
    H = (L*G - 2*M*F + N*E)/2/denominator

    return K, H

def makefunction(exprs, assignto, funcname='func', returncodestr=False, usenumba=True):
    """
    Given sympy expressions list `expr` and a list of variable names
    `assignto`, it creates a function. It returns a function object if
    `returncodestr` = False. Otherwise, it returns a formatted function code
    as a string with the name of the function given by `funcname`. If
    `usenumba` is False it will not produce a Numba Jitted function.
    """
    codestr = [
        'import math',
        'from math import sqrt',       # Bug in Sympy, need to handle sqrt separately
    ]
    if usenumba:
        codestr += [
            'import numba',
            '\n@numba.njit'
        ]
    else:
        codestr.append('')             # Just to introduce a line break

    codestr += [
        'def {0}(x, y):'.format(funcname),
        '\n    ############## Sub-expressions ##############'
    ]

    # Now the codegeneration part, first eliminate common sub-expressions
    replacements, reduced_exprs = sympy.cse(exprs, optimizations='basic')
    for lhs, rhs in replacements:
        codestr.append('    {} = {}'.format(lhs, sympy.pycode(rhs)))

    codestr.append('\n    ############## Final Expressions ##############')
    for lhs, rhs in zip(assignto, reduced_exprs):
        codestr.append('    {} = {}'.format(lhs, sympy.pycode(rhs)))

    codestr.append('\n    return {}'.format(', '.join(assignto)))
    funccode = '\n'.join(codestr)

    if returncodestr:
        return funccode
    else:
        exec(funccode, globals())
        return globals()[funcname]


#!/usr/bin /env python3
from mat import *

A = readm('A.csv')
b = readm('b.csv')

def solve(A, b):
    # YOUR CODE HERE
    import numpy as np
    a,b = np.array(A), np.array(b)
    n= len(A[0])
    x = np.array([0]*n)
    #1.elimination
    """n = len(A[0])
    print(f'n={n}')
    """
    for k in range(0,n-1): # pivot equation #k
        #print(f'เลือกสมการที่ {k}')
        for j in range(k+1, n): #eliminate eq #j
            if a[j,k] !=0.0:
            #print(f'\tกำจัดตัวแปรที่ {k},ออกจากสมการที่ {j}')
                lam = a[j][k]/a[k][k]
            #update A[j][k เป็นต้นไป]
                a[j,k:n] = a[j,k:n] - lam*a[k,k:n]
            #A[j][k+2] = A[j][k+2] - lam*A[k][k+2]
            #A[j][k+3] = A[j][k+3] - lam*A[k][k+3]
            #print(f'\t\tlambda={lam}')
            #update b[j]
                b[j] = b[j] - lam* b[k]

        """printm(A)
        print(b)
        """
    #2 back substitution
    for k in range(n-1, -1, -1): #2,1,0
        x[k] = (b[k] - np.dot(a[k,k+1:n], x[k+1:n]))/a[k,k]
        #print(f' k={k}')
        #A[k,0:n]*x[k:] = b[k:]
    #x = []
    return x.flatten()
print( solve (A,b))


"""
********************************************************************************
FDM for 2D wave equation
********************************************************************************
"""

import time
import numpy as np
import matplotlib.pylab as plt

def FDM(xmin, xmax, nx, dx,
        ymin, ymax, ny, dy,
        nt, dt,
        x, y, u, c, BC):
    # FDM for reference
    u[0, :, :] = np.exp(-(x - 3) ** 2) * np.exp(-(y - 3) ** 2)
    u[1, :, :] = u[0, :, :]

    t0 = time.time()
    for n in range(1, nt - 1):
        # if n % int(1e2) == 0:
        #     print(">>>>> FDM computing... n =", n)
        for i in range(1, nx - 1):
            for j in range(1, ny - 1):
                u[n + 1, i, j] = 2 * u[n, i, j] - u[n - 1, i, j] \
                                + (c * dt / dx) ** 2 * (u[n, i + 1, j] - 2 * u[n, i, j] + u[n, i - 1, j]) \
                                + (c * dt / dy) ** 2 * (u[n, i, j + 1] - 2 * u[n, i, j] + u[n, i, j - 1])
        if BC == "Dir":
            for i in range(1, nx - 1):
                u[n + 1, i,  0] = 0.
                u[n + 1, i, -1] = 0.
            for j in range(1, ny - 1):
                u[n + 1,  0, j] = 0.
                u[n + 1, -1, j] = 0.
            u[n,  0,  0] = 0.
            u[n, -1,  0] = 0.
            u[n,  0, -1] = 0.
            u[n, -1, -1] = 0.
        elif BC == "Neu":
            for i in range(1, nx - 1):
                u[n + 1, i,  0] = u[n + 1, i,  1]
                u[n + 1, i, -1] = u[n + 1, i, -2]
            for j in range(1, ny - 1):
                u[n + 1,  0, j] = u[n + 1,  1, j]
                u[n + 1, -1, j] = u[n + 1, -2, j]
            u[n,  0,  0] = (u[n,  1,  0] + u[n,  0,  1]) / 2
            u[n, -1,  0] = (u[n, -2,  0] + u[n, -1,  1]) / 2
            u[n,  0, -1] = (u[n,  1, -1] + u[n,  0, -2]) / 2
            u[n, -1, -1] = (u[n, -2, -1] + u[n, -1, -2]) / 2
    t1 = time.time()
    elps = t1 - t0
    print(">>>>> elapse time for FDM (sec):", elps)
    print(">>>>> elapse time for FDM (min):", elps / 60.)

    # plot FDM solutions
    fig  = plt.figure(figsize = (16, 4))
    # snapshot 1
    ax   = fig.add_subplot(1, 3, 1, projection = "3d")
    surf = ax.plot_surface(x, y, u[0, :, :], cmap = "coolwarm", linewidth = 0, vmin = -.5, vmax = .5)
    ax.set_xlim(xmin, xmax)
    ax.set_ylim(ymin, ymax)
    ax.set_zlim(-1, 1)
    ax.set_xlabel("x", fontstyle = "italic")
    ax.set_ylabel("y", fontstyle = "italic")
    ax.set_zlabel("u (x, y)", fontstyle = "italic")
    # snapshot 2
    ax   = fig.add_subplot(1, 3, 2, projection = "3d")
    surf = ax.plot_surface(x, y, u[100, :, :], cmap = "coolwarm", linewidth = 0, vmin = -.5, vmax = .5)
    ax.set_xlim(xmin, xmax)
    ax.set_ylim(ymin, ymax)
    ax.set_zlim(-1, 1)
    ax.set_xlabel("x", fontstyle = "italic")
    ax.set_ylabel("y", fontstyle = "italic")
    ax.set_zlabel("u (x, y)", fontstyle = "italic")
    # snapshot 3
    ax   = fig.add_subplot(1, 3, 3, projection = "3d")
    surf = ax.plot_surface(x, y, u[-1, :, :], cmap = "coolwarm", linewidth = 0, vmin = -.5, vmax = .5)
    ax.set_xlim(xmin, xmax)
    ax.set_ylim(ymin, ymax)
    ax.set_zlim(-1, 1)
    ax.set_xlabel("x", fontstyle = "italic")
    ax.set_ylabel("y", fontstyle = "italic")
    ax.set_zlabel("u (x, y)", fontstyle = "italic")
    plt.show()

    return u


from sympy import *
import sys
sys.path.insert(1, '..')
from quaternion_R_utils import *

px_1, py_1, pz_1 = symbols('px_1 py_1 pz_1')
q0_1, q1_1, q2_1, q3_1 = symbols('q0_1 q1_1 q2_1 q3_1')
px_2, py_2, pz_2 = symbols('px_2 py_2 pz_2')
q0_2, q1_2, q2_2, q3_2 = symbols('q0_2 q1_2 q2_2 q3_2')
ksi_1, eta_1, ksi_2, eta_2, ksi_01, eta_01, ksi_02, eta_02, c_1, c_2 = symbols('ksi_1 eta_1 ksi_2 eta_2 ksi_01 eta_01 ksi_02 eta_02 c_1 c_2');

position_symbols_1 = [px_1, py_1, pz_1]
quaternion_symbols_1 = [q0_1, q1_1, q2_1, q3_1]
position_symbols_2 = [px_2, py_2, pz_2]
quaternion_symbols_2 = [q0_2, q1_2, q2_2, q3_2]
c_symbols = [c_1, c_2]
all_symbols = position_symbols_1 + quaternion_symbols_1 + position_symbols_2 + quaternion_symbols_2

bx=px_2-px_1
by=py_2-py_1
bz=pz_2-pz_1
b=Matrix([[0, -bz, by], [bz, 0, -bx], [-by, bx, 0]])
C_1t=Matrix([[1, 0, -ksi_01], [0, 1, -eta_01], [0, 0, -c_1]]).transpose()
C_2=Matrix([[1, 0, -ksi_02], [0, 1, -eta_02], [0, 0, -c_2]])

camera_matrix_1 = matrix44FromQuaternion(px_1, py_1, pz_1, q0_1, q1_1, q2_1, q3_1)
R_1t=camera_matrix_1[:-1,:-1].transpose()
camera_matrix_2 = matrix44FromQuaternion(px_2, py_2, pz_2, q0_2, q1_2, q2_2, q3_2)
R_2=camera_matrix_2[:-1,:-1]
ksieta_1=Matrix([[ksi_1, eta_1, 1]])
ksieta_2t=Matrix([[ksi_2, eta_2, 1]]).transpose()

obs_eq = Matrix([[0]]) - ksieta_1 * C_1t * R_1t * b * R_2 * C_2 * ksieta_2t
obs_eq_jacobian = obs_eq.jacobian(all_symbols)

print(obs_eq)
print(obs_eq_jacobian)

with open("metric_camera_coplanarity_quaternion_wc_jacobian.h",'w') as f_cpp:
    f_cpp.write("inline void observation_equation_metric_camera_coplanarity_quaternion_wc(double &delta, double ksi_01, double eta_01, double c_1, double ksi_1, double eta_1, double px_1, double py_1, double pz_1, double q0_1, double q1_1, double q2_1, double q3_1, double ksi_02, double eta_02, double c_2, double ksi_2, double eta_2, double px_2, double py_2, double pz_2, double q0_2, double q1_2, double q2_2, double q3_2)\n")
    f_cpp.write("{")
    f_cpp.write("delta = %s;\n"%(ccode(obs_eq[0])))
    f_cpp.write("}")
    f_cpp.write("\n")
    f_cpp.write("inline void observation_equation_metric_camera_coplanarity_quaternion_wc_jacobian(Eigen::Matrix<double, 1, 14, Eigen::RowMajor> &j, double ksi_01, double eta_01, double c_1, double ksi_1, double eta_1, double px_1, double py_1, double pz_1, double q0_1, double q1_1, double q2_1, double q3_1, double ksi_02, double eta_02, double c_2, double ksi_2, double eta_2, double px_2, double py_2, double pz_2, double q0_2, double q1_2, double q2_2, double q3_2)\n")
    f_cpp.write("{")
    for i in range (12):
        f_cpp.write("j.coeffRef(%d,%d) = %s;\n"%(0,i, ccode(obs_eq_jacobian[0,i])))
    f_cpp.write("}")


##%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
##          Multivariate outlier detection via Mahalanobis distances
## %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

#%% read data
import numpy as np
data_2Doutlier = np.loadtxt('simple2D_outlier.csv', delimiter=',')

# plot
import matplotlib.pyplot as plt
plt.plot(data_2Doutlier[:-5,0], data_2Doutlier[:-5,1], '.', markeredgecolor='k', markeredgewidth=0.5, ms=9)
plt.plot(data_2Doutlier[-5:,0], data_2Doutlier[-5:,1], '.r', markeredgecolor='k', markeredgewidth=0.5, ms=11)
plt.xlabel('x1'), plt.ylabel('x2')
plt.title('Raw measurements')

#%% compute Mahalanobis distances
from sklearn.covariance import EmpiricalCovariance

emp_cov = EmpiricalCovariance().fit(data_2Doutlier)
MD_emp_cov = emp_cov.mahalanobis(data_2Doutlier)

#%% transform Mahalanobis distances into normal distribution via cubic-root
MD_cubeRoot = np.power(MD_emp_cov, 0.333)

#%% find hampel identifier bounds
from scipy import stats

median = np.median(MD_cubeRoot)
sigma_MAD = stats.median_absolute_deviation(MD_cubeRoot)

upperBound_MD_emp_cov = np.power(median+3*sigma_MAD, 3)
lowerBound_MD_emp_cov = np.power(median-3*sigma_MAD, 3)

#%% plot Mahalanobis distances with bounds (last 5 samples are the outliers)
plt.figure(), plt.plot(MD_emp_cov[:-5], '.', markeredgecolor='k', markeredgewidth=0.5, ms=9)
plt.plot(np.arange(300,305), MD_emp_cov[-5:], '.r', markeredgecolor='k', markeredgewidth=0.5, ms=11)

plt.hlines(upperBound_MD_emp_cov, 0, 305, colors='r', linestyles='dashdot', label='Upper bound')
plt.hlines(lowerBound_MD_emp_cov, 0, 305, colors='r', linestyles='dashed', label='Lower bound')

plt.xlabel('sample #'), plt.ylabel('Mahalanobis distance')
plt.title('Mahalanobis distances of raw measurements')
plt.legend(loc='upper left')


#!/usr/bin/env python3
#
# Copyright 2018 by Marc Weitz
#
# This script is licensed under the MIT-license.
# See https://opensource.org/licenses/MIT for more information

import matplotlib.pyplot as plt
from numpy.polynomial import Polynomial

def seq(start, end, by=0.01):
    return [xx * by for xx in range(int(start / by), int(end / by))]

def plot_polynomial(f, x, c=4):
        y = [f(x_i) for x_i in x]

        if ii == 0:
            plt.plot(x, [y_i - c for y_i in y], ls='-',
                     c="black", label=round(ii, 1))
            plt.plot(x, [y_i + c for y_i in y], ls='-', c="black")
        else:
            plt.plot(x, [y_i - c for y_i in y], ls='--', label=round(ii, 1))

plt.subplot(2, 3, 1)
plt.ylim((-10, 14))
plt.title('$f(x) = a \cdot x + c$')
for ii in seq(-0.5, 0.2, by=0.1):
    plot_polynomial(Polynomial([0., 1. + ii]), seq(0, 4))

plt.subplot(2, 3, 2)
plt.title('$f(x) = a \cdot x^2 + c$')
for ii in seq(-0.5, 0.2, by=0.1):
    plot_polynomial(Polynomial([0., 0., 1. + ii]), seq(0, 4))

plt.subplot(2, 3, 3)
plt.title('$f(x) = a \cdot x^3 + c$')
for ii in seq(-0.5, 0.2, by=0.1):
    plot_polynomial(Polynomial([0., 0., 0., 1. + ii]), seq(0, 4))

lgd = plt.legend(title='$\delta = a - a_{ref}$',
                 bbox_to_anchor=(1.04, 1.04),
                 loc="upper left")
plt.savefig('../plots/examples.pdf', bbox_extra_artists=(lgd,), bbox_inches='tight',
            figsize=(12, 3), dpi=80, transparent=True)


import numpy as np

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

def random(batchSize, pointCount, dimCount):
    return np.random.rand(batchSize, pointCount, dimCount).astype(np.float32)

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

def regular(pointCount, dimCount):
    pointsPerDim = round(pointCount**(1./dimCount))
    assert (pointCount == pointsPerDim**dimCount), "Regular %dD grid with %d points not possible" % (dimCount, pointCount)
    maxValue = 1 - 1/pointsPerDim
    p = np.meshgrid(*[np.linspace(i, j, pointsPerDim) for i,j in zip([0]*dimCount, [maxValue]*dimCount)])
    p = np.transpose(np.asarray(p), list(range(dimCount+1))[::-1])
    p = np.reshape(p, (pointCount, dimCount))
    return p.astype(np.float32)

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

def jittered(batchSize, pointCount, dimCount):
    reg = regular(pointCount, dimCount)
    cellSize = 1. / round(pointCount**(1./dimCount))
    noise = np.random.uniform(0, cellSize, (batchSize, pointCount, dimCount)).astype(np.float32)
    return np.expand_dims(reg, 0) + noise

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

# samples that are regular in the first gridDimCount dimensions
# and random in the remaining dimensions
def griddedRandom(batchSize, pointCount, dimCount, griddingDims=0):
    if griddingDims == 0:
        return random(batchSize, pointCount, dimCount)
    assert (dimCount >= griddingDims), "Number of gridded dimensions is larger than base dimensionality"
    reg = regular(pointCount, griddingDims)
    reg = np.tile(np.expand_dims(reg, 0), [batchSize, 1, 1])
    ran = random(batchSize, pointCount, dimCount - griddingDims)
    return np.append(reg, ran, -1)


# Data Preprocessing

# Importing the libraries
import numpy as np                  # numpy is the library that contains mathematical tools
import matplotlib.pyplot as plt     # help plot charts
import pandas as pd                 # import data sets and manage data sets

# 1. Importing the dataset
df = pd.read_csv('Data.csv' )

# 2. Need to determine the data feature (Independent data) and the dependent variables
X_feature = df.iloc[:, :-1].values     # symbol : means we take all the rows, and all the columns except the last one.
Y_dependent = df.iloc[:, 3].values

# Tip: ‘NaN’ has to be replaced by ‘np.nan’. This is due to an update in the sklearn library.

# Taking care of missing data
#   scikit-learn : machine learning library in python
# sklearn.impute: help process missing data
from sklearn.impute import SimpleImputer
imp = SimpleImputer(missing_values = np.nan, strategy='mean')
# make the imputer fit on X_feature
imp = imp.fit(X_feature[:, 1:3])  # Upper bound is excluded, so index 1 and 2 columns are included
#Replace the missing data of the matrix X_feature by the mean of the column
X_feature[:, 1:3] = imp.transform(X_feature[:, 1:3])

# # Splitting the dataset into the Training set and Test set
# from sklearn.cross_validation import train_test_split
# X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 0)
#
# # Feature Scaling
# """from sklearn.preprocessing import StandardScaler
# sc_X = StandardScaler()
# X_train = sc_X.fit_transform(X_train)
# X_test = sc_X.transform(X_test)
# sc_y = StandardScaler()
# y_train = sc_y.fit_transform(y_train)"""

Machine Learning A-Z/Part 1 - Data Preprocessing/data_preprocessing_template.py


import sklearn
from sklearn.datasets import make_moons
from array import array
import matplotlib.pyplot as plt
import numpy as np

X = Y = []
alpha = 0.015
numRecords = 0

def plt_decision_boundary(pred_func):
    x_min, x_max = X[:, 0].min() - .5, X[:, 0].max() + .5
    y_min, y_max = X[:, 1].min() - .5, X[:, 1].max() + .5
    h = 0.01

    xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))

    Z = pred_func(np.c_[xx.ravel(), yy.ravel()])
    Z = Z.reshape((xx.shape))

    plt.contourf(xx, yy, Z, cmap=plt.cm.Spectral)
    plt.scatter(X[:, 0], X[:, 1], c=Y, cmap=plt.cm.Spectral)

def predict(x, net):
    W1, B1, W2, B2 = net['W1'], net['B1'], net['W2'], net['B2']

    z1 = x.dot(W1) + B1
    a1 = np.tanh(z1)
    z2 = a1.dot(W2) + B2
    expScores = np.exp(z2)
    probs = expScores / np.sum(expScores, axis=1, keepdims=True)

    return np.argmax(probs, axis=1)

def loss(net):
    W1, B1, W2, B2 = net['W1'], net['B1'], net['W2'], net['B2']

    z1 = X.dot(W1) + B1
    a1 = np.tanh(z1)
    z2 = a1.dot(W2) + B2
    expScores = np.exp(z2)
    probs = expScores / np.sum(expScores, axis=1, keepdims=True)

    predictClass = np.argmax(probs, axis=1)
    loss = 0.5*np.power(predictClass - Y, 2)

    return np.sum(loss)/numRecords

# 350
def build(hlayer, epochs=3050):
    W1 = np.random.randn(2, hlayer)
    B1 = np.zeros((1, hlayer))
    W2 = np.random.randn(hlayer, 2)
    B2 = np.zeros((1, 2))

    net = {}
    lossFn = []

    for i in xrange(0, epochs):
        z1 = X.dot(W1) + B1
        a1 = np.tanh(z1)
        z2 = a1.dot(W2) + B2
        expScores = np.exp(z2)
        probs = expScores / np.sum(expScores, axis=1, keepdims=True)

        delta2 = probs
        delta2[range(numRecords), Y] -= 1

        delta1 = delta2.dot(W2.T) * (1 - np.power(a1, 2))

        dW2 = (a1.T).dot(delta2)
        dB2 = np.sum(delta2, axis=0, keepdims=True)
        dW1 = (X.T).dot(delta1)
        dB1 = np.sum(delta1, axis=0, keepdims=True)

        W1 += -alpha*(dW1)
        B1 += -alpha*(dB1)
        W2 += -alpha*(dW2)
        B2 += -alpha*(dB2)

        net = {
            "W1": W1,
            "B1": B1,
            "W2": W2,
            "B2": B2
        }

        error = loss(net)*100
        lossFn.append([i, error])
        if i%25 == 0:
            print i, "th Iteration, Loss: ", error, "%"
    return net, np.array(lossFn)

if __name__ == "__main__":
    X, Y = make_moons(700,noise=0.3, random_state=0)
    numRecords = len(X)

    net, lossFn = build(3)

    plt.subplot(211)
    plt.title("Boundary Classification")
    plt_decision_boundary(lambda x: predict(x, net))

    plt.subplot(212)
    plt.ylabel("Error")
    plt.xlabel("Epochs")
    plt.title("Error Functions")
    plt.plot(lossFn[:, 0], lossFn[:, 1])
    plt.show()


import tensorflow as tf
import numpy as np
import math

#caclulate DCT basis
def cal_scale(p,q):
    if p==0:
        ap = 1/(math.sqrt(8))
    else:
        ap = math.sqrt(0.25)
    if q==0:
        aq = 1/(math.sqrt(8))
    else:
        aq = math.sqrt(0.25)

    return ap,aq

def cal_basis(p,q):
    basis = np.zeros((8,8))
    ap,aq = cal_scale(p,q)
    for m in range(0,8):
        for n in range(0,8):
            basis[m,n] = ap*aq*math.cos(math.pi*(2*m+1)*p/16)*math.cos(math.pi*(2*n+1)*q/16)

    return basis

def load_DCT_basis_64():
    basis_64 = np.zeros((8,8,64))
    idx = 0
    for i in range(8):
        for j in range(8):
            basis_64[:,:,idx] = cal_basis(i,j)
            idx = idx + 1
    return basis_64

#networks functions
def l2(x):
    return tf.nn.l2_loss(x)

def weight_variable(shape):
    initial = tf.truncated_normal(shape, stddev=0.1)
    return tf.Variable(initial)

def bias_variable(shape):
    initial = tf.constant(0.1, shape=shape)
    return tf.Variable(initial)

def batch_norm(x,phase):
    return tf.contrib.layers.batch_norm(x, decay=0.9, epsilon=0.001, center=True, scale=True, is_training=phase)

def conv2d_v(x,W):
    return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding="VALID")

def conv2d(x,W):
    return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding="SAME")

def trans_conv2d(x,W,output_shape):
    return tf.nn.conv2d_transpose(x, W, output_shape, strides=[1, 2, 2, 1], padding="SAME")

def conv2d_2(x,W):
    return tf.nn.conv2d(x, W, strides=[1, 2, 2, 1], padding="SAME")

def conv2d_8(x,W):
    return tf.nn.conv2d(x, W, strides=[1, 8, 8, 1], padding="SAME")

def max_pool_2x2(x):
    return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME")

def max_pool_3x1_2_v(x):
    return tf.nn.max_pool(x, ksize=[1, 3, 1, 1], strides=[1, 2, 1, 1], padding="VALID")

def avg_pool_2x2(x):
    return tf.nn.avg_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME")

def FC(x,W):
    return tf.matmul(x,W)

def ReLU(x):
    return tf.nn.relu(x)


import math
import numpy as np
from logger import logger

def gaussian(x, mu, sigma):
    coeff = 1/(2*math.pi*sigma**2)**0.5
    power = (-(x - mu)**2)/(2*sigma**2)
    return coeff * math.exp(power)

def get_normal_vector(points: np.ndarray):
    """
    Note: Direction of normal vector depends on right hand rule.
    p0, p1, p2 = points
    v01, v12 = p1 - p0, p2 - p1
    """
    if points.shape != (3, 3):
        logger.error(f"Received points matrix of size {points.shape}. Expected (3, 3).")
        raise Exception
    p0, p1, p2 = points

    # These two vectors are in the plane
    v01 = p1 - p0
    v12 = p2 - p1

    # The cross product is a vector normal to the plane
    result = np.cross(v01, v12)
    return result


import numpy as np
from scipy.special import comb

def pac_noise(m_samples, n_features, context_size, delta=0.05, factor: float = 1.0):
    return factor*np.sqrt(2/m_samples*np.log(2*comb(n_features, context_size)/delta))

def approx_comb(n, m):
    n*np.log(n) - m*np.log(m) - (n-m)*np.log(n-m)


from keras import backend
import numpy

# define new accuracy : R^2 --------------------------------------------------------------------------------------------
def R_squared(y_true, y_pred):

    SS_res = backend.sum(backend.square(y_true - y_pred))
    SS_tot = backend.sum(backend.square(y_true - backend.mean(y_true)))
    r2 = 1 - SS_res / (SS_tot + backend.epsilon())

    return r2

def r_squared(y_true, y_pred):

    y1 = numpy.subtract(y_pred, y_true)
    y2 = numpy.subtract(y_pred, numpy.mean(y_true))

    ys1 = numpy.square(y1)
    ys2 = numpy.square(y2)

    S1 = numpy.sum(ys1)
    S2 = numpy.sum(ys2)

    r2 = 1 - S1 / (S2 + 10**-30)

    return r2

def mse(y_true, y_pred):

    y1 = numpy.subtract(y_true, y_pred)
    y2 = numpy.square(y1)
    y3 = numpy.mean(y2)

    return y3


#
#	root-scanning.py
#	Finding root using scanning method
#
#	Sparisoma Viridi | https://butiran.github.io/
#
#	Execute: py root-scanning.js
#
#	20210128
#	1235 Start this program.
#	1758 Continue after test_function test.
#	1806 Add reference 1, just now about it.
#	1828 Test it and ok.
#	1855 Add reference 2, use it.
#	20210210
#	0527 Typo node --> py.
#
#	References
#	1. Glenn Maynard, "Answer to 'Why are there no ++ and --
#	   operators in Python?'", StackOverflow, 6 Sep 2010 23:57,
#	   url https://stackoverflow.com/a/3654936 [20210128].
#	2. sanjoy_62, "numpy.sign() in Python", GeeksforGeeks,
#	   03 Oct 2019, url
#	   https://www.geeksforgeeks.org/numpy-sign-in-python/
#	   [20210128].
#

# Import necessary libraries
import numpy as np

# Define a test function
def test_function(x):
	a = 0.05
	x1 = -1
	x2 = 3.45
	x3 = 8
	y = a*(x-x1)*(x-x2)*(x-x3)
	return y

# Define input
f = test_function
xbeg = 2
xend = 5
dx = 1

# Define default message
xroot = "not found";

# Do iteration
Nstep = 0;
x = xbeg;

while x <= xend:
	# Increase Nstep;
	Nstep += 1

	# Calculate S0 and S
	if x == xbeg:
		S0 = np.sign(f(x))
	else:
		S = np.sign(f(x))

	# Check S0.S for root
	if x > xbeg:
		if S0 * S < 0:
			xroot = x - 0.5 * dx;
			break;

	x += dx;

# Display result
print("f(x)   0.05(x+1)(x-3.45)(x-8)");
print("Δx    ", dx, sep="")
print("xbeg  ", xbeg, sep="")
print("xend  ", xend, sep="")
print("Nstep ", Nstep, sep="")
print("xroot ", xroot, sep="")