-
Notifications
You must be signed in to change notification settings - Fork 1
Description
After taking another look at the discrepancy for k61r
(equivalent to Champion) I have found a bug.
TLDR k61r
works the very first time it is called in a match but every subsequent match after that a section of it does not behave properly.
k61r
should randomly defect after the 25th turn (dependent on the opponent's cooperation ratio).
It behaves as expected the very first time it is used but for every subsequent call it does not. Here is a minimal failing code snippet:
>>> import axelrod as axl
>>> import axelrod_fortran as axlf
>>> def run_champion_v_alternator():
... player = axlf.Player("k61r")
... opponent = axl.Alternator()
... match = axl.Match((player, opponent))
... axl.seed(0)
... interactions = match.play()
... axl.seed(0)
... assert interactions == match.play()
>>> run_champion_v_alternator()
---------------------------------------------------------------------------
AssertionError Traceback (most recent call last)
<ipython-input-1-70d9b1c75b35> in <module>()
13 axl.seed(0)
14 assert interactions == match.play()
---> 15 run_champion_v_alternator()
<ipython-input-1-70d9b1c75b35> in run_champion_v_alternator()
12
13 axl.seed(0)
---> 14 assert interactions == match.play()
15 run_champion_v_alternator()
AssertionError:
Note however that if I rerun the function in the same session it does not fail:
>>> run_champion_v_alternator()
However, it is indeed the very first play of the match that is correct. Here starting a new Python session:
>>> import axelrod as axl
>>> import axelrod_fortran as axlf
>>> player = axlf.Player("k61r")
>>> opponent = axl.Alternator()
>>> match = axl.Match((player, opponent))
>>> axl.seed(0)
>>> interactions = match.play()
>>> interactions[25:30] # k61r *does* defect
[(C, D), (C, C), (C, D), (D, C), (C, D)]
>>> axl.seed(0)
>>> interactions = match.play()
>>> interactions[25:30] # k61r no longer defects
[(C, D), (C, C), (C, D), (C, C), (C, D)]
Modifying this line in the Fortran code https://github.com/Axelrod-Python/TourExec/blob/master/src/strategies/k61r.f#L11:
COPRAT = FLOAT(ICOOP) / FLOAT(ITURN)
to just be a constant:
COPRAT = 0.5
gives consistent (although obviously incorrect) behaviour which makes me believe that somehow something is happening which means we're not "reloading" things correctly (I'm guessing here)?
Things I have tried:
- Change how our reset method works in
axlf
to "dump" and reload the CDLL but that's not come to anything (although I've pretty much been fumbling around in the dark). - Looked at the make file to see if this could be due to a compilation flag but that's waaaaaay above my understanding of things so who knows...
- Change the Fortran code in
k61r
but again with no success - Note that if we could resolve this by modifyingaxlf
that would be preferable (from the point of view of the narrative of "using the code as is").
Some good news, I've run the following:
for strategy in axlf.all_strategies:
player = axlf.Player(strategy)
for opponent in axl.basic_strategies:
match = axl.Match((player, opponent()))
axl.seed(0)
interactions = match.play()
axl.seed(0)
if interactions != match.play():
print(player, opponent)
and the only player that seems to be affected by this bug is k61r
. (FYI, I attempted to add this snippet as a test but that doesn't fail because the test is run out of order, in other words it doesn't detect the bug because k61r
has already been called by another test).