Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Strategy From the PRISON (http://www.lifl.fr/IPD/ipd.frame.html) #724

Merged
merged 13 commits into from
Sep 28, 2016
6 changes: 4 additions & 2 deletions axelrod/strategies/_strategies.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
TitForTat, TitFor2Tats, TwoTitsForTat, Bully, SneakyTitForTat,
SuspiciousTitForTat, AntiTitForTat, HardTitForTat, HardTitFor2Tats,
OmegaTFT, Gradual, ContriteTitForTat, SlowTitForTwoTats, AdaptiveTitForTat)

from .worse_and_worse import (WorseAndWorse, KnowledgeableWorseAndWorse)

# Note: Meta* strategies are handled in .__init__.py

Expand Down Expand Up @@ -195,12 +195,14 @@
Willing,
WinShiftLoseStay,
WinStayLoseShift,
WorseAndWorse,
KnowledgeableWorseAndWorse,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you put this in alphabetical order please.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

ZDExtort2,
ZDExtort2v2,
ZDExtort4,
ZDGTFT2,
ZDGen2,
ZDSet2,
e,

]
59 changes: 59 additions & 0 deletions axelrod/strategies/worse_and_worse.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
from axelrod import Actions, Player, random_choice

C, D = Actions.C, Actions.D

class WorseAndWorse (Player):
"""
Defects with probability of 'current turn / 1000'. Therefore
it is more and more likely to defect as the round goes on.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add:

Source code available at the download tab of [PRISON1998].

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would this line go at the end of line 10 or do you want it as part of the names section?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In between line 10 and the names section. So:

Defects with probability ...
is more likely ...

Source code available ...

Names...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the clarification, I have now made this change.


Source code available at the download tab of [PRISON1998]_


Names:
- Worse and Worse: [PRISON1998]_

"""

name = 'Worse and Worse'
classifier = {
'memory_depth': float('inf'),
'stochastic': True,
'makes_use_of': set(),
'long_run_time': False,
'inspects_source': False,
'manipulates_source': False,
'manipulates_state': False
}

def strategy(self, opponent):
current_round = len(self.history) + 1
probability = 1 - float(current_round) / 1000
return random_choice(probability)


class KnowledgeableWorseAndWorse (Player):
"""
This strategy is based on 'Worse And Worse' but will defect with probability
of 'current turn / total no. of turns'.

Copy link
Member

@drvinceknight drvinceknight Sep 27, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This still needs a names section:

    Names:
        - Knowledgeable Worse and Worse: Original name by Adam Phol

Names:
- Knowledgeable Worse and Worse: Original name by Adam Pohl
"""

name = 'Knowledgeable Worse and Worse'
classifier = {
'memory_depth': float('inf'),
'stochastic': True,
'makes_use_of': set(['length']),
'long_run_time': False,
'inspects_source': False,
'manipulates_source': False,
'manipulates_state': False
}

def strategy(self, opponent):
current_round = len(self.history) + 1
expected_length = self.match_attributes['length']
probability = 1 - float(current_round) / expected_length
return random_choice(probability)
3 changes: 1 addition & 2 deletions axelrod/tests/unit/test_player.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# -*- coding: utf-8 -*-
import copy
import inspect
import random
import unittest
Expand Down Expand Up @@ -89,7 +88,7 @@ def test_responses(test_class, P1, P2, history_1, history_2, responses,
"""

if random_seed:
random.seed(random_seed)
axelrod.seed(random_seed)
# Force the histories, In case either history is impossible or if some
# internal state needs to be set, actually submit to moves to the strategy
# method. Still need to append history manually.
Expand Down
107 changes: 107 additions & 0 deletions axelrod/tests/unit/test_worse_and_worse.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
"""Test for the Worse and Worse strategies."""

import axelrod

from .test_player import TestPlayer

C, D = axelrod.Actions.C, axelrod.Actions.D

class TestWorseAndWorse(TestPlayer):

name = "Worse and Worse"
player = axelrod.WorseAndWorse
expected_classifier = {
'memory_depth': float('inf'),
'stochastic': True,
'makes_use_of': set(),
'long_run_time': False,
'inspects_source': False,
'manipulates_source': False,
'manipulates_state': False
}

def test_strategy(self):
"""
Test that the strategy gives expected behaviour
"""

axelrod.seed(8)
opponent = axelrod.Cooperator()
player = axelrod.WorseAndWorse()
match = axelrod.Match((opponent, player), turns=10)
self.assertEqual(match.play(), [('C', 'C'),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once you've made the expected change, this might change but either way it would be good if you picked a seed that didn't just have WorseAndWorse cooperate (ie choose one that gives a mix of C and D). Change the strategy first though.

('C', 'C'),
('C', 'C'),
('C', 'C'),
('C', 'C'),
('C', 'C'),
('C', 'D'),
('C', 'C'),
('C', 'C'),
('C', 'C')])

# Test that behaviour does not depend on opponent
opponent = axelrod.Defector()
player = axelrod.WorseAndWorse()
axelrod.seed(8)
match = axelrod.Match((opponent, player), turns=10)
self.assertEqual(match.play(), [('D', 'C'),
('D', 'C'),
('D', 'C'),
('D', 'C'),
('D', 'C'),
('D', 'C'),
('D', 'D'),
('D', 'C'),
('D', 'C'),
('D', 'C')])


class TestWorseAndWorseRandom(TestPlayer):

name = "Knowledgeable Worse and Worse"
player = axelrod.KnowledgeableWorseAndWorse
expected_classifier = {
'memory_depth': float('inf'),
'stochastic': True,
'makes_use_of': set(['length']),
'long_run_time': False,
'inspects_source': False,
'manipulates_source': False,
'manipulates_state': False
}

def test_strategy(self):
"""
Test that the strategy gives expected behaviour
"""
axelrod.seed(1)
opponent = axelrod.Cooperator()
player = axelrod.KnowledgeableWorseAndWorse()
match = axelrod.Match((opponent, player), turns=5)
self.assertEqual(match.play(), [('C', 'C'),
('C', 'D'),
('C', 'D'),
('C', 'D'),
('C', 'D')])

# Test that behaviour does not depend on opponent
opponent = axelrod.Defector()
player = axelrod.KnowledgeableWorseAndWorse()
axelrod.seed(1)
match = axelrod.Match((opponent, player), turns=5)
self.assertEqual(match.play(), [('D', 'C'),
('D', 'D'),
('D', 'D'),
('D', 'D'),
('D', 'D')])

# Test that behaviour changes when does not know length.
axelrod.seed(1)
match = axelrod.Match((opponent, player), turns=5,
match_attributes={'length': float('inf')})
self.assertEqual(match.play(), [('D', 'C'),
('D', 'C'),
('D', 'C'),
('D', 'C'),
('D', 'C')])
7 changes: 5 additions & 2 deletions docs/reference/all_strategies.rst
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ Here are the docstrings of all the strategies in the library.
.. automodule:: axelrod.strategies.gobymajority
:members:
:undoc-members:
.. automodule:: axelrod.strategies.gradualkiller
:members:
:undoc-members:
.. automodule:: axelrod.strategies.grudger
:members:
:undoc-members:
Expand Down Expand Up @@ -120,6 +123,6 @@ Here are the docstrings of all the strategies in the library.
.. automodule:: axelrod.strategies.titfortat
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not delete gradualkiller.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't, if you look further up you will see that I moved it so that the list was in alphabetical order again.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah great: my mistake :) 👍

:members:
:undoc-members:
.. automodule:: axelrod.strategies.gradualkiller
.. automodule:: axelrod.strategies.worse_and_worse
:members:
:undoc-members:
:undoc-members:
4 changes: 2 additions & 2 deletions docs/tutorials/advanced/classification_of_strategies.rst
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ strategies::
... }
>>> strategies = axl.filtered_strategies(filterset)
>>> len(strategies)
35
37


Or, to find out how many strategies only use 1 turn worth of memory to
Expand Down Expand Up @@ -81,7 +81,7 @@ length of each match of the tournament::
... }
>>> strategies = axl.filtered_strategies(filterset)
>>> len(strategies)
4
5

Note that in the filterset dictionary, the value for the 'makes_use_of' key
must be a list. Here is how we might identify the number of strategies that use
Expand Down