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

# draw N random points in the [0,1]x[0,1] square
N = 100

x1 = np.random.rand(N)
x2 = np.random.rand(N)
X = np.vstack(zip(np.ones(N),x1, x2))
print X.shape

# use cosine to define positive and negative classes
y = np.array([1 if np.cos(2*np.pi*X[i,1]) / 2 + 0.5 > X[i,2] else 0 for i in range(N)])

p = plt.figure()
p1 = p.add_subplot(121)
p1.plot(x1,x2,'rx')

# create a cosine curve and add to the plot
x = np.arange(0, 1.0, 0.01)
fx = np.cos(2*np.pi*x) / 2 + 0.5
p1.plot(x, fx, lw=2)

# discriminate those above and below the curve
p2 = p.add_subplot(122)
for i in range(N):
    if y[i]==1:
        p2.plot(x1[i],x2[i],'bo')  # o (bolinhas) azuis (blue)
    else:
        p2.plot(x1[i],x2[i],'ro')  # o (bolinhas) vermelhas (red)
                
p2.plot(x, fx, lw=2)
plt.show()


"""
Explanation: Exercício 2-2
Classificação de pontos: classes positiva (1) e negativa (0)
Caso não linearmente separável
1.Gerar os pontos. Vamos supor que a superfície de separação é uma cosenoide
Os que estão em um lado da curva são positivos (azuis) e os que estão do outro lado são negativos (vermelhos)
End of explanation
"""


from funcoes2 import sigmoid, gradientDescent2, computeCost2

# chutar uns pesos iniciais
w = np.zeros(3)
initialCost = computeCost2(X, y, w)
print 'Initial cost: ', initialCost

# Some gradient descent settings
iterations = 1000
alpha = 0.05

# run gradient descent
w, J_history = gradientDescent2(X, y, w, alpha, iterations)

finalCost = computeCost2(X, y, w)
print 'Final cost: ', finalCost

print w

R = X.dot(w)
#print R

for i in range(N):
    if sigmoid(R[i]) > 0.5:
    #if X[i,:].dot(w) > 0:
        plt.plot(X[i,1], X[i,2], 'bx')
    else:
        plt.plot(X[i,1], X[i,2], 'ro')

plt.plot(x, fx, lw=2)
xs = np.arange(0, max(X[:,1]), 0.01)
fxs = [(-w[0]-w[1]*p)/w[2] for p in x ]
plt.plot(xs, fxs, lw=2)
plt.xlabel('x1')
plt.ylabel('x2')
plt.show()

"""
Explanation: 2. Aplicar a regressão logística
End of explanation
"""


X = np.vstack(zip(np.ones(N),x1, x2, x1*x1, x1*x2, x2*x2))
print X.shape

# chutar uns pesos iniciais
w = np.zeros(6)
initialCost = computeCost2(X, y, w)
print 'Initial cost: ', initialCost

# Some gradient descent settings
iterations = 1500
alpha = 0.1

# run gradient descent
w, J_history = gradientDescent2(X, y, w, alpha, iterations)

finalCost = computeCost2(X, y, w)
print 'Final cost: ', finalCost

print w

R = X.dot(w)
#print R

for i in range(N):
    if sigmoid(R[i]) > 0.5:
    #if X[i,:].dot(w) > 0:
        plt.plot(X[i,1], X[i,2], 'bx')
    else:
        plt.plot(X[i,1], X[i,2], 'ro')
plt.plot(x, fx, lw=2)
plt.xlabel('x1')
plt.ylabel('x2')
plt.show()

"""
Explanation: 3. Adicionar novos features (polinomiais)
O dado original estendido é da forma $(1,x_1,x_2)$. Vamos criar novas features. Expecificamente, consideraremos $(1,x_1,x_2,x_1^2,x_1\,x_2, x_2^2)$ e aplicar a regressão logística ao dado "ampliado".
End of explanation
"""


