Der Einsatz evolutionärer Computermodelle bei der Untersuchung historischer und politischer Fragestellungen
|
Eckhart Arnold
6.1 Tournament.py
"""Classes for matches and tournaments.
The the instances of the classes Match and Tournament can be
connected to visualizing objects by appending a signal function to
the signalXXXXXX lists of the class instance. Signal functions have
the general form:
function(originating_object, *argument_list)
See the source code to find out which signals are defined and which
arguments are passed to the signals.
"""
###########################################################
#
# class Match
#
###########################################################
class Match:
"""Let two strategies play one series of iterated prisoners
dilemmas and record the results.
signals:
signalROUND_FINISHED (match) - sent when one round of the match
has been finished
flags (read the "state" field, e.g. m = Match(p1, p2); flag=m.state):
MATCH_READY - match has not yet started
MATCH_RUNNING - match is currently running
MATCH_FINISHED - match has been finished
"""
def __init__(self, player1, player2, T=5, R=3, P=1, S=0, w=200):
"""Initialize class with player strategies."""
self.signalROUND_FINISHED = [] # dummy function with
# argument list
self.player1 = player1 # strategy of player 1
self.player2 = player2 # strategy of player 2
self.moves1 = [] # sequence of moves from player 1
self.moves2 = [] # sequence of moves from player 2
self.score1 = 0 # absolute score of player 1
self.score2 = 0 # absolute score of player 2
self.round = 0 # number of round
self.state = "MATCH_READY"
self.T = T # reward for defecting if the other player cooperated
self.R = R # reward for mutual cooperation
self.P = P # "reward" for mutual defection
self.S = S # "reward" for cooperation if the other player defected
self.w = w # number of rounds
def score(self, m1, m2):
"""Return the score of player one for the moves m1 and m2 of
player one and player two respectively. In order to determine the
score of player two just swap the parameters m1 and m2."""
if (m1, m2) == (0, 1): return self.T
elif (m1, m2) == (1, 1): return self.R
elif (m1, m2) == (0, 0): return self.P
else: return self.S
def nextRound(self):
"""Let the players meet and update the respective variables with
the results. Then, determine if iteration stops after this round
(random > w). Return 0 if it does, 1 otherwise."""
self.round += 1
m1 = self.player1.nextMove(self.round, self.moves1, self.moves2)
m2 = self.player2.nextMove(self.round, self.moves2, self.moves1)
self.moves1.append(m1)
self.moves2.append(m2)
self.score1 += self.score(m1, m2)
self.score2 += self.score(m2, m1)
if self.round >= self.w: return 0
else: return 1
def match(self):
"""Play one match. Call notifier function after each round."""
self.state = "MATCH_RUNNING"
cont = 1
while cont:
cont = self.nextRound()
for s in self.signalROUND_FINISHED: s(self) # callback
self.state = "MATCH_FINISHED"
###########################################################
#
# class Tournament
#
###########################################################
class Tournament:
"""Set up and play a tournament.
signals:
signalENLIST_PLAYER (tournament, player)
a new player has been enlisted
signalNEW_MATCH (tournament, match)
a new match has just begun
signalMATCH_COMPLETED (tournament, match)
match "match" has been completed
signalTOURNAMENT_FINISHED (tournament)
the tournament has been finished
flags (read the "state" field, e.g. t = Tournament(); flag=t.state):
TOURNAMENT_READY - match has not yet started
TOURNAMENT_RUNNING - match is currently running
TOURNAMENT_FINISHED - match is finished
"""
def __init__(self, name = "Tournament", T=5, R=3, P=1, S=0, w=200):
"""Initialize class with match notifier and
identification string."""
self.signalENLIST_PLAYER = []
self.signalNEW_MATCH = []
self.signalMATCH_COMPLETED = []
self.signalTOURNAMENT_FINISHED = []
self.name = name # identification string
self.player = [] # list of players
self.match = [] # list of matches
self.score = {} # dictionary of player scores (indexed by players)
self.state = "TOURNAMENT_READY"
self.T = T # Parameters defining the reward (or punishment resp.)
self.R = R # for cooperation or defection.
self.P = P # These parameters are directly passed to Match.__init__()
self.S = S
self.w = w # number of rounds
def __cmpfunc(self, p1, p2):
if self.score[p1] > self.score[p2]: return -1
elif self.score[p1] == self.score[p2]: return 0
else: return 1
def enlistPlayer(self, newPlayer):
"""Adds a new Player to the tournament."""
self.player.append(newPlayer)
for s in self.signalENLIST_PLAYER: s(self, newPlayer)
def runTournament(self):
"""Run the tournament.
Let each player play once against every other player.
Invoke signalNEW_MATCH before a new new match is started and
signalMATCH_COMPLETED after it is finished. When all matches are
completed, calculate the scores of the players and sort
self.player according to the players rank in the tournament."""
self.state = "TOURNAMENT_RUNNING"
self.match = []
for p in self.player: self.score[p] = 0
for i in range(len(self.player)):
for k in range(i+1, len(self.player)):
p1 = self.player[i]
p2 = self.player[k]
m = Match(p1, p2, self.T, self.R, self.P, self.S, self.w)
self.match.append(m)
for s in self.signalNEW_MATCH: s(self, m)
m.match()
self.score[p1] += m.score1
self.score[p2] += m.score2
for s in self.signalMATCH_COMPLETED: s(self, m)
self.player.sort(self.__cmpfunc)
self.state = "TOURNAMENT_FINISHED"
for s in self.signalTOURNAMENT_FINISHED: s(self)
|
|
g+
f
@