-
Notifications
You must be signed in to change notification settings - Fork 0
/
Predictor.py
152 lines (137 loc) · 6.56 KB
/
Predictor.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
145
146
147
148
149
150
151
152
from Game import Game
from Player import Player
import Experts
import random
import math
class DeterministicPlayer(Player):
def __init__(self, game, beta, experts):
assert(0 < beta < 1)
Player.__init__(self, game)
self.beta = beta
self.weightedExperts = [(expert, 1) for expert in experts]
def makeMove(self):
predictWeights = {move : 0 for move in self.game.getMoves()}
for (expert, weight) in self.weightedExperts:
predictWeights[expert.predict()] += weight
expectedValue = {move : 0 for move in self.game.getMoves()}
for move1 in self.game.getMoves():
for move2 in self.game.getMoves():
expectedValue[move1] += predictWeights[move2] * self.game.testMoves(move1, move2)
return max(expectedValue, key = lambda key : expectedValue[key])
def observeMove(self, move):
# Multiply weight by beta if the expert's prediction was wrong
self.weightedExperts = [(expert, weight * (self.beta ** (expert.predict() != move)))
for (expert, weight) in self.weightedExperts]
# Normalize weights so max weight is 1, to prevent us from getting
# extremely small weights (unless an expert is terrible compared to the best)
(_, maxweight) = max(self.weightedExperts, key = lambda ew : ew[1])
self.weightedExperts = [(expert, weight/maxweight) for (expert, weight) in self.weightedExperts]
for (expert, _) in self.weightedExperts: expert.observeMove(move)
class NondeterministicPlayer(Player):
def __init__(self, game, beta, experts):
assert(0 < beta < 1)
Player.__init__(self, game)
self.beta = beta
self.weightedExperts = [(expert, 1) for expert in experts]
def makeMove(self):
predictWeights = {move : 0 for move in self.game.getMoves()}
for (expert, weight) in self.weightedExperts:
predictWeights[expert.predict()] += weight
expectedValue = {move : 0 for move in self.game.getMoves()}
for move1 in self.game.getMoves():
for move2 in self.game.getMoves():
expectedValue[move1] += predictWeights[move2] * self.game.testMoves(move1, move2)
experts, weights = zip(*self.weightedExperts)
chosenMove = random.choices(experts, weights, k=1)[0].predict()
possiblePlays = [move for move in self.game.getMoves() if not self.game.testMoves(move, chosenMove)]
moveWeights = [math.exp(expectedValue[move]) for move in possiblePlays]
return random.choices(possiblePlays, moveWeights, k=1)[0]
def observeMove(self, move):
# Multiply weight by beta if the expert's prediction was wrong
self.weightedExperts = [(expert, weight * (self.beta ** (expert.predict() != move)))
for (expert, weight) in self.weightedExperts]
# Normalize weights so max weight is 1, to prevent us from getting
# extremely small weights (unless an expert is terrible compared to the best)
(_, maxweight) = max(self.weightedExperts, key = lambda ew : ew[1])
self.weightedExperts = [(expert, weight/maxweight) for (expert, weight) in self.weightedExperts]
for (expert, _) in self.weightedExperts: expert.observeMove(move)
def playAgainstUser(G, player):
playerWins = 0
pythonWins = 0
ties = 0
while True:
pythonMove = player.makeMove()
playerMove = input("Enter your move: ")
if playerMove == "exit": return
if playerMove not in G.getMoves():
print ("Unknown move: " + playerMove)
continue
if G.testMoves(pythonMove, playerMove) == 1:
pythonWins += 1
successStr = "I win!"
elif G.testMoves(pythonMove, playerMove) == -1:
playerWins += 1
successStr = "You win!"
else:
ties += 1
successStr = "We tied!"
player.observeMove(playerMove)
print("I made the move: " + pythonMove + ". " + successStr)
print("Me: {} ({}, {}) You : {} Ties : {}".format(pythonWins,\
pythonMove, [weight for (expert, weight) in player.weightedExperts],\
playerWins,\
ties))
def playAgainstSelf(G, player1, player2, numRounds):
playerWins = 0
pythonWins = 0
ties = 0
count1 = {move : 0 for move in G.getMoves()}
count2 = {move : 0 for move in G.getMoves()}
for i in range(numRounds):
pythonMove = player1.makeMove()
playerMove = player2.makeMove()
count1[pythonMove] += 1
count2[playerMove] += 1
if G.testMoves(pythonMove, playerMove) == 1:
pythonWins += 1
elif G.testMoves(pythonMove, playerMove) == -1:
playerWins += 1
else:
ties += 1
player1.observeMove(playerMove)
player2.observeMove(pythonMove)
print("Me: {} ({}, {}) You : {} ({}, {}) Ties : {}".format(pythonWins,\
pythonMove, [weight for (expert, weight) in player1.weightedExperts],\
playerWins,\
playerMove, [weight for (expert, weight) in player2.weightedExperts],\
ties))
print (count1)
print (count2)
def main():
RPSGame = Game()
RPSGame.loadFromJson("Games/rpsdk.json")
RPSGame.addMove("four")
#RPSGame.removeRelation("scissors", "paper")
#RPSGame.addRelation("scissors", "four")
#RPSGame.addRelation("four", "paper")
RPSGame.removeRelation("knight", "dragon")
RPSGame.addRelation("knight", "four")
RPSGame.addRelation("four", "dragon")
#player1 = NondeterministicPlayer(RPSGame, .5, \
# [Experts.KthLastMoveExpert(RPSGame.getMoves(), k) for k in range(4)])
#player2 = NondeterministicPlayer(RPSGame, .5, \
# [Experts.KthLastMoveExpert(RPSGame.getMoves(), k) for k in range(4)])
#player2 = DeterministicPlayer(RPSGame, .5, \
# [Experts.WeightedLastMovesExpert(RPSGame.getMoves(), [1, 1])])
player1 = NondeterministicPlayer(RPSGame, .5, \
[Experts.NondeterministicSequenceExpert(RPSGame.getMoves(), k) for k in range(5)])
player2 = NondeterministicPlayer(RPSGame, .5, \
[Experts.NondeterministicSequenceExpert(RPSGame.getMoves(), k) for k in range(5)])
#player1 = NondeterministicPlayer(RPSGame, .5, \
# [Experts.NondeterministicSequenceExpert(RPSGame.getMoves(), k) for k in range(5)])
#player2 = NondeterministicPlayer(RPSGame, .5, \
# [Experts.NondeterministicSequenceExpert(RPSGame.getMoves(), k) for k in range(5)])
playAgainstSelf(RPSGame, player1, player2, 100000)
#playAgainstUser(RPSGame, player1)
if __name__ == "__main__":
main()