def rollDice():
    return random.randint(1, 6)
    
def generate():
    N = 10000
    trials = {}
    for i in range(N):
        d1 = rollDice()
        d2 = rollDice()
        s = d1 + d2
        trials[s] = trials.get(s, 0) + 1
    return trials

data = generate()
plt.bar(list(data.keys()), list(data.values()))
plt.xticks(range(1, 12))
plt.show()

"""
Explanation: Gaussian distribution
Generation sample by rolling dices many times
End of explanation
"""


def calcCumulativeDist(data):
    s = {}
    for i, v in enumerate(data.values()):
        s[i] = s.get(i - 1, 0) + v
    return s

def takeSamples(rangeFrom, rangeTo, n):
    return [random.randint(rangeFrom, rangeTo) for i in range(n)]

cumulativDist = calcCumulativeDist(data)

plt.plot(list(cumulativDist.keys()), list(cumulativDist.values()))
plt.show()

"""
Explanation: Cumulative Distribution
End of explanation
"""


data = generate()
data

"""
Explanation: Parameter Estimation
We try to find mean and variance using given data points.
End of explanation
"""


N = np.sum(list(data.values()))

m = sum(k*v for k, v in data.items()) / N
m

"""
Explanation: 1. Finding mean
Mean is simply the average of data points. N is the number of data points.
$$
\mu = \frac{1}{N} \sum_{i}^{N} x_{i} \
$$
End of explanation
"""


variance = sum(np.power(k - m, 2) for k, v in data.items() for i in range(v)) / N
variance

"""
Explanation: 2. Finding variance
To find the variance we sum the squared differences from the mean. Finally we take the average of the sum. 
$$
\sigma^{2} = \frac{1}{N} \sum_{i}^{N}(x_{i} - \mu)^{2} \
$$
End of explanation
"""


def calc_p(x, m, variance):
    return 1/ np.sqrt(2*np.pi * np.sqrt(variance)) * np.exp(- np.power(x-m, 2) / 2*variance)

ps = dict((i, calc_p(i, m, variance)) for i in np.linspace(1, 12, 120))

plt.plot(list(ps.keys()), list(ps.values()))
plt.xticks(range(1, 13))
plt.show()

dict((i, calc_p(i, m, variance)) for i in range(1, 13))

"""
Explanation: Gaussian (Normal) distribution
Say $ X \in \mathbb{R} $ if x is distirbuted Gaussian with mean $\mu$, variance $\sigma^{2}$.
$$
X \sim \mathcal{N}(\mu,\,\sigma^{2})
$$
$$
p(x, \mu, \sigma^{2}) = \frac{1}{\sqrt{2\pi } \ \sigma} exp(-\frac{(x-\mu)^{2}}{2\sigma^{2}})
$$
End of explanation
"""


def cumulativeCDF(x, m, stdv):
    return 0.5 * (1 + math.erf((x-m)/ (stdv * math.sqrt(2)) ))

print(cumulativeCDF(8, m, np.sqrt(variance)))

plt.plot(
    np.linspace(1, 13, 130), 
    list(cumulativeCDF(i, m, np.sqrt(variance))  for i in np.linspace(1, 13, 130)))
plt.grid(True)
plt.show()

df = pd.read_csv("data/student/student-mat.csv", ";")
df.sample(5)

df.info()

df[["G1", "G3", "G2"]].plot.hist(stacked=True, bins=20,alpha=0.5)

def is_anomoly(g1, g2, g3, df):
    g1_d = df["G1"].describe()
    g2_d = df["G2"].describe()
    g3_d = df["G3"].describe()
    print(g1_d)
    print(g2_d)
    print(g3_d)
    p1 = calc_p(g1, g1_d["mean"], np.power(g1_d["std"], 2))
    p2 = calc_p(g2, g2_d["mean"], np.power(g2_d["std"], 2))
    p3 = calc_p(g3, g3_d["mean"], np.power(g3_d["std"], 2))
    print(p1)
    print(p2)
    print(p3)
    print(np.log(p1)+np.log(p2)+np.log(p3))
is_anomoly(10.908861, 10.713924, 10.415190, df)

from pandas.tools.plotting import scatter_matrix
scatter_matrix(df[
    ["G1", "G2", "G3", "age", "Walc", "goout", "absences", "studytime","famsize"]], alpha=0.2, figsize=(12, 12), diagonal='kde')
plt.show()

"""
Explanation: Density Estimation & Cumulative Density Function
What is the probability of rolling two dice whose sum is between 2 and 8? Cumulative distribution function is as follows:
$$
\phi(x, \mu, \sigma) = \frac{1}{2} \ (1 + erf( \frac{x-\mu}{\sigma \sqrt{2}} ) ) 
$$
End of explanation
"""


