-
Notifications
You must be signed in to change notification settings - Fork 1
/
bayesDice.py
144 lines (122 loc) · 4.58 KB
/
bayesDice.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
##############################################################
#### Bayes Dice program
#### Author: Nathan N.
#### Date Created: 8.4.2013
#### Last Updated: 8.4.2013
#### Notes: Bayesian probability methods attempt to make
#### decisions based on degrees of belief or confidence.
#### As a result, it allows for decision-making in the
#### face of incomplete information, which is often what
#### people encounter in the real world. This program
#### models a scenario in which there are 5 multisided
#### dice in a box. One die is picked out at random.
#### It's type is unknown at the start. The goal of this
#### program is to use Bayesian probability as a model
#### for machine learning in order to make a decision in
#### the face of incomplete information--in this case, a
#### guess at the die type that was selected based on the
#### random die roll results.
##############################################################
#### PROGRAM IS MODELED OFF OF BAYESIAN PROBABILITY TABLE BELOW ####
#### In this example there are 5 types of dice.
####
#### H (Hypthesis) is the guess that a particular die was selected.
####
#### P(H) (Prior) is the probabity of having picked that particular die
#### out of the total dice types available to select from.
####
#### D (Data) is the roll result.
####
#### P(D|H) (Likelihood) is the probability of the stated roll result (6)
#### occuring (D; data), given that the hypothesis (H) is True.
####
#### P(H) * P(D|H) is the non normalized probability that the
#### Hypothesis is True, given the roll result (data).
####
#### P(H|D) (Posterior) is the normalized probability that H is True, given
#### the data. This is our objective. P(H)P(D|H) / SUM(ALL P(H)P(D|H))
#### Note that this term becomes the Prior on future rolls.
# H P(H) D P(D|H) P(H)*P(D|H) P(H|D)
# 4 .2 6 .00000 .0000 .00000
# 6 .2 6 .16667 .03333 .39216
# 8 .2 6 .125 .025 .29412
# 12 .2 6 .08333 .08333 .19608
# 20 .2 6 .025 .11765 .11765
import random
import sys
class Dice:
def __init__(self):
self.data = []
self.singleRollResult = 0
self.diceTypes = [4, 6, 8, 12, 20]
self.guess = None
self.r = random
self.r.seed()
self.priors = [1.0 / len(self.diceTypes) for x in self.diceTypes]
self.dieType = None
self.likelihoods = [1.0 / x for x in self.diceTypes]
self.prePosteriors = [a * b for a,b in zip(self.priors, self.likelihoods)]
self.sumPrePosteriors = sum(x for x in self.prePosteriors)
self.posteriors = [x / self.sumPrePosteriors for x in self.prePosteriors]
def selectRandomDie(self):
self.dieType = self.diceTypes[self.r.randrange(len(self.diceTypes))]
def roll(self):
rollResult = self.r.randrange(1, self.dieType)
self.singleRollResult = rollResult
self.data.append(rollResult)
def updatePriors(self):
self.priors = [x for x in self.posteriors]
def updateLikelihoods(self):
for i in xrange(len(self.diceTypes) - 1):
for roll in self.data:
if roll > self.diceTypes[i]:
self.likelihoods[i] = 0
def updatePrePosteriors(self):
self.prePosteriors = [a * b for a,b in zip(self.priors, self.likelihoods)]
def updatePosteriors(self):
self.sumPrePosteriors = 0
self.sumPrePosteriors = sum(x for x in self.prePosteriors)
self.posteriors = [x / self.sumPrePosteriors for x in self.prePosteriors]
def updateGuess(self):
self.updatePriors()
self.updateLikelihoods()
self.updatePrePosteriors()
self.updatePosteriors()
def printGuess():
i = 0
print('Best guess:')
for die in dice.diceTypes:
asterisk = ''
if dice.posteriors[i] >= .8:
asterisk = '*'
dice.guess = die
print(f'{asterisk}{die}-sided die: {round(dice.posteriors[i] * 100, 2)} percent probability.')
i += 1
def main():
promptAnyKey = None
rollagain = 'y'
i = 0
print('\n-------------------------------------\n')
print(f'There are {len(dice.diceTypes)} dice in a box full of multisided dice: {dice.diceTypes}.')
print('You have selected one at random.')
print('This program will attempt to guess which die was picked based on your rolls.\n')
dice.selectRandomDie()
while promptAnyKey is None:
promptAnyKey = input('Press enter to roll.\n')
while rollagain != 'x':
i += 1
dice.roll()
print(f'\nYou rolled a {dice.singleRollResult}.\n')
dice.updateGuess()
printGuess()
rollagain = input('\nPress ENTER to roll. (x to exit)\n')
rollagain = rollagain.lower()
if dice.guess == dice.dieType:
status = 'The program guessed CORRECTLY!'
else:
status = 'The program did NOT guess correctly!'
print(f'The die selected was a {dice.dieType}-sided die! {status} {i} total rolls')
sys.exit()
if __name__ == '__main__':
dice = Dice()
main()