Skip to content

Bug with k61 #62

@drvinceknight

Description

@drvinceknight

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 modifying axlfthat 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).

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions