Skip to content

Commit

Permalink
added work carried out on dice
Browse files Browse the repository at this point in the history
  • Loading branch information
carmelgafa committed Feb 14, 2024
1 parent 8d2fdfe commit 00ac45a
Show file tree
Hide file tree
Showing 11 changed files with 361 additions and 0 deletions.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
114 changes: 114 additions & 0 deletions ml_algorithms/src/introduction_to_computation/dice/dishonest_casino.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import matplotlib.pyplot as plt
from fair_die import FairDie
from loaded_die import LoadedDie
from numpy import mean
from numpy import arange
import random
import enum



class DiceThrow(enum.Enum):
FAIR = enum.auto()
LOADED = enum.auto()
class DishonestCasino():

def __init__(self, p1:float, p2:float) -> None:
self.fair_die = FairDie()
self.biased_die = LoadedDie()
self.p_1 = p1
self.p_2 = p2



def play(self, number_of_tosses:int)->float:

results = []
next_toss = DiceThrow.FAIR
prob_first_toss = random.uniform(0,1)
if prob_first_toss > 0.5:
next_toss = DiceThrow.LOADED

fair_toss_counter = 0
loaded_toss_counter = 0


for i in range(number_of_tosses):

if next_toss == DiceThrow.FAIR:
fair_toss_counter += 1
prob_next_toss = random.uniform(0,1)
if prob_next_toss > self.p_1:
next_toss = DiceThrow.LOADED
else:
loaded_toss_counter += 1
prob_next_toss = random.uniform(0,1)
if prob_next_toss > self.p_2:
next_toss = DiceThrow.FAIR

# print(fair_toss_counter)
# print(loaded_toss_counter)

fair_tosses = self.fair_die.roll_multiple(fair_toss_counter)
loaded_tosses = self.biased_die.roll_multiple(loaded_toss_counter)

mean_all_tosses = (sum(fair_tosses)+sum(loaded_tosses))/(fair_toss_counter+loaded_toss_counter)

return mean_all_tosses



def play_old(self, number_of_tosses:int)->list:

results = []

next_toss = DiceThrow.FAIR
prob_first_toss = random.uniform(0,1)
if prob_first_toss > 0.5:
next_toss = DiceThrow.LOADED

for i in range(number_of_tosses):

if next_toss == DiceThrow.FAIR:
results.append(self.fair_die.roll())
prob_next_toss = random.uniform(0,1)
if prob_next_toss > self.p_1:
next_toss = DiceThrow.LOADED
else:
results.append(self.biased_die.roll())
prob_next_toss = random.uniform(0,1)
if prob_next_toss > self.p_2:
next_toss = DiceThrow.FAIR
return results

def simulate(self, t:int):
'''Simulate Method'''
simulation_mean = self.play(t)
return mean(simulation_mean)


def test(self)->None:

avg_results = []
number_tosses_per_play = 100
number_of_plays = 10
for i in range(0, number_of_plays):
# append the average opf the tosses
play = self.play(number_tosses_per_play)
mean_play = mean(play)
print(mean_play)
avg_results.append(mean_play)

# possible averages from 1 to 6 in steps of 0.5
# ie 11 possible outcomes
avg_frequencies = []
for i in arange(1,6.5, 0.5):
avg_frequencies.append(avg_results.count(i) / number_of_plays)

print(avg_frequencies)
plt.bar(arange(1,6.5, 0.5).tolist(), avg_frequencies, color='g', edgecolor='blue', width=0.5)
plt.show()

if __name__=='__main__':
casino = DishonestCasino(0.99, 0.1)
print(casino.play(100000))
46 changes: 46 additions & 0 deletions ml_algorithms/src/introduction_to_computation/dice/fair_casino.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import matplotlib.pyplot as plt
from fair_die import FairDie
from numpy import mean
from numpy import arange
import numpy as np

class FairCasino():

def __init__(self) -> None:
self.die = FairDie()

def play(self, number_of_tosses:int=2):
return self.die.roll_multiple(number_of_tosses)


def simulate(self, t):
mean_res = mean(self.play(t))
print(mean_res)
return mean_res

def test(self)->None:

avg_results = []

number_of_plays = 5000
for i in range(0, number_of_plays):
# append the average opf the tosses
play = self.play()
mean_play = mean(play)
avg_results.append(mean_play)

# possible averages from 1 to 6 in steps of 0.5
# ie 11 possible outcomes
avg_frequencies = []
for i in arange(1,6.5, 0.5):
avg_frequencies.append(avg_results.count(i) / number_of_plays)

print(avg_frequencies)

plt.bar(arange(1,6.5, 0.5), avg_frequencies, color='g', edgecolor='blue', width=0.5)
plt.show()


if __name__=='__main__':
casino = FairCasino()
casino.test()
34 changes: 34 additions & 0 deletions ml_algorithms/src/introduction_to_computation/dice/fair_die.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import random
import numpy as np
import matplotlib.pyplot as plt

class FairDice:

def __init__(self) -> None:
...

def roll(self)->int:
return random.randint(1,6)

def roll_multiple(self, number_of_tosses):
x = np.random.random((number_of_tosses, 1)).squeeze()
return np.ceil(x*6)

def test_die(self)->None:
outcomes = []

number_of_trials = 5000
for i in range(number_of_trials):
outcomes.append(self.roll())

results = []
for i in np.arange(1,7):
results.append(outcomes.count(i) / number_of_trials)

plt.bar(np.arange(1,7), results, color='g', edgecolor='blue', width=1)
plt.show()


if __name__ == '__main__':
die = FairDice()
die.roll_multiple(10)
49 changes: 49 additions & 0 deletions ml_algorithms/src/introduction_to_computation/dice/loaded_die.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
'''Loaded dice implementation'''

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

class LoadedDice:
'''A loaded dice. probabilities for each number defined in __init_'''

def __init__(self) -> None:
'''Initializes new dice'''
self.probabilities = np.array([0.5, 0.1, 0.1, 0.1, 0.1, 0.1])
self.cumul_array = np.cumsum(self.probabilities)

def roll(self)->int:
'''rolls dice'''
precision = 3
random_number = random.randint(0, 10 ** precision) / float(10 ** precision)
mapped_cumul = self.cumul_array - random_number
rolled_number = np.where(mapped_cumul > 0, mapped_cumul, np.inf).argmin()
return rolled_number + 1

def roll_multiple(self, number_of_tosses):
'''rolls dice multiple times'''
x = np.random.random((number_of_tosses, 1)).squeeze()
x = np.ceil(x*10)-4
x[x<=0] = 1
return x


def test_die(self)->None:
'''executes a test for the dice'''
outcomes = []

number_of_trials = 5000
for i in range(number_of_trials):
outcomes.append(self.roll())

results = []
for i in np.arange(1,7):
results.append(outcomes.count(i) / number_of_trials)

plt.bar(np.arange(1,7), results, color='g', edgecolor='blue', width=1)
plt.show()

if __name__ == '__main__':
die = LoadedDice()
print(die.roll_multiple(100000))
die.test_die()
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
Mean for dishonest casino with p1:0.99 and p2:0.05 is 3.489619392000011
Mean for dishonest casino with p1:0.95 and p2:0.1 is 3.4474341769999897
Mean for dishonest casino with p1:0.9 and p2:0.2 is 3.388901595000009

-----------------------------------------------------------------------------

Task 3
------

Dishonest simulation with p1 = 0.9 and p2 = 0.2
mean: 3.388901595, variance:3.096003910988601e-05, standard deviation:0.005564174611735869

Fair Simulation
mean: 3.4999125920000007, variance:2.8043537135249523e-05, standard deviation:0.005295614896803725

Note for next Calculation
-------------------------

To use the estimated variance to find the sample size required to obtain a RMSE error of 0.001,
we use the following formula:

n = ( (z * sigma / e)^2 )

Where:

n is the sample size
z is the standard normal deviate (e.g. for a 95% confidence level, z = 1.96)
sigma is the estimated population standard deviation
e is the desired margin of error (e.g. e = 0.001)

This formula states that the sample size required to achieve a certain level of
precision (e) is proportional to the square of the ratio of the standard deviation
to the margin of error.

It's important to note that this formula assumes that your estimator has a normal
distribution and that the true variance is known or has been estimated from a sample.

Also, it's important to know that this is only a rough estimation,
and the sample size required for a specific problem may be influenced
by other factors like the distribution of the data, the model assumptions,
the desired confidence level, etc.





-----------------------------------------------------------------------------

70 changes: 70 additions & 0 deletions ml_algorithms/src/introduction_to_computation/dice/simulations.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
from dishonest_casino import DishonestCasino
from fair_casino import FairCasino
import csv
import numpy as np

def fair_casino_simulation():
casino = FairCasino()

mean_results = []

for _ in range(10000):
mean_results.append(casino.simulate(100000))

with open('fair_results.csv', 'w') as f:
write = csv.writer(f)
write.writerow(mean_results)

mean = sum(mean_results)/len(mean_results)
print('Mean for fair casino: ', mean)


def dishonest_casino_simulation_run(p1:float, p2:float):

mean_results = []

casino = DishonestCasino(p1, p2)

for _ in range(10000):
mean_results.append(casino.simulate(100000))

with open(f'dishonest_results-{p1}-{p2}.csv', 'w', encoding='UTF-8') as f:
write = csv.writer(f)
write.writerow(mean_results)

simulations_mean = sum(mean_results)/len(mean_results)
print(f'Mean for dishonest casino with p1:{p1} and p2:{p2} is {simulations_mean}')


def dishonest_casino_simulation():

dishonest_casino_simulation_run(0.99, 0.05)
dishonest_casino_simulation_run(0.95, 0.1)
dishonest_casino_simulation_run(0.9, 0.2)


def calculate_variance(simulation_data:np.array):#type:ignore
simulation_mean = np.mean(simulation_data)

variance = np.sum(np.square(simulation_data - simulation_mean))/(np.size(simulation_data)-1)
standard_deviation = np.sqrt(variance)

print(f'mean: {simulation_mean}, variance:{variance}, standard deviation:{standard_deviation}')


def dishonest_trial_variance_calculation():
print('Dishonest simulation with p1 = 0.9 and p2 = 0.2')
simulation_data = np.genfromtxt('dishonest_results-0.9-0.2.csv', delimiter=',')
calculate_variance(simulation_data)


def fair_trial_variance_calculation():
print('Fair Simulation')
simulation_data = np.genfromtxt('fair_results.csv', delimiter=',')
calculate_variance(simulation_data)

if __name__ == '__main__':
# fair_casino_simulation()
# dishonest_casino_simulation()
dishonest_trial_variance_calculation()
fair_trial_variance_calculation()

0 comments on commit 00ac45a

Please sign in to comment.