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

Add new strategy SelfSteem #866

Merged
merged 12 commits into from
Feb 26, 2017
2 changes: 2 additions & 0 deletions axelrod/strategies/_strategies.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
Retaliate, Retaliate2, Retaliate3, LimitedRetaliate, LimitedRetaliate2,
LimitedRetaliate3)
from .sequence_player import SequencePlayer, ThueMorse, ThueMorseInverse
from .selfsteem import SelfSteem
from .shortmem import ShortMem
from .titfortat import (
TitForTat, TitFor2Tats, TwoTitsForTat, Bully, SneakyTitForTat,
Expand Down Expand Up @@ -210,6 +211,7 @@
RevisedDowning,
Ripoff,
RiskyQLearner,
SelfSteem,
ShortMem,
Shubik,
SlowTitForTwoTats,
Expand Down
49 changes: 49 additions & 0 deletions axelrod/strategies/selfsteem.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
from axelrod.actions import Action, Actions
from axelrod.player import Player

from math import pi, sin
import random

C, D = Actions.C, Actions.D


class SelfSteem(Player):
"""
This strategy is based on the feeling with the same name.
Copy link
Member

Choose a reason for hiding this comment

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

self esteem?

Copy link
Member Author

Choose a reason for hiding this comment

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

It means self esteem, that's how its named in the paper. I decided not to change it.

It is modeled on the sine curve(f = sin( 2* pi * n / 10 )), which varies
with the current iteration.
Copy link
Member

@marcharper marcharper Feb 22, 2017

Choose a reason for hiding this comment

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

current iteration n is the round number? (I see below the answer is yes but the docstring could say so.)

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes.


If f > 0.95, 'ego' of the algorithm is inflated; always defects.
If 0.95 > |f| > 0.3, rational behavior; follows TitForTat algortithm.
Copy link
Member

Choose a reason for hiding this comment

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

This line is creating an error as sphinx is confused by |f|. I suggest replacing it with abs(f).

If 0.3 > f > -0.3; random behavior.
If f < -0.95, algorithm is at rock bottom; always cooperates.
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 add Names ... see: http://axelrod.readthedocs.io/en/latest/tutorials/contributing/strategy/writing_the_new_strategy.html This will also require you to add the reference to docs/reference/bibliography.rst.

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 also add this strategy to docs/reference/all_strategies.rst

Copy link
Member

Choose a reason for hiding this comment

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

"""

name = 'SelfSteem'
Copy link
Member

Choose a reason for hiding this comment

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

What is the name of this strategy?

SelfSteem or SelfEsteem? Across module names etc you seem to be combining these.

Copy link
Member Author

Choose a reason for hiding this comment

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

It is SelfSteem. I mistakenly named the test test_selfesteem instead of test_selfsteem.

classifier = {
'memory_depth': 1,
'stochastic': False,
'makes_use_of': set(),
'long_run_time': False,
'inspects_source': False,
'manipulates_source': False,
'manipulates_state': False
}

def strategy(self, opponent: Player) -> Action:
turns_number = len(self.history)
sine_value = sin(2*pi*turns_number/10)
Copy link
Member

Choose a reason for hiding this comment

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

PEP8: 2 * pi * ...


if sine_value > 0.95:
return D

elif abs(sine_value) < 0.95 and abs(sine_value) > 0.3:
return opponent.history[-1]

elif sine_value < 0.3 and sine_value > -0.3:
return random.choice((C, D))
Copy link
Member

Choose a reason for hiding this comment

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

Better to use the inbuilt random_choice() from axelrod.random_.


else:
return C


37 changes: 37 additions & 0 deletions axelrod/tests/unit/test_selfesteem.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
"""Tests for the SelfSteem strategy."""

import axelrod
import random
from .test_player import TestPlayer

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

class TestSelfSteem(TestPlayer):

name = "SelfSteem"
player = axelrod.SelfSteem
expected_classifier = {
'memory_depth': 1,
'stochastic': False,
'makes_use_of': set(),
'inspects_source': False,
'manipulates_source': False,
'manipulates_state': False
}

def test_strategy(self):
# Check for f > 0.95
self.responses_test([D], [C] * 2 , [C] * 2 )
self.responses_test([D], [C] * 13, [C] * 13)

# Check for f < -0.95
self.responses_test([C], [C] * 7, [C] * 7)
self.responses_test([C], [C] * 18, [D] * 18)

# Check for 0.95 > abs(f) > 0.3
self.responses_test([C], [C], [C])
self.responses_test([D], [C] * 16, [D] * 16)
self.responses_test([C], [D] * 9, [C] * 9)


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 get rid of the blank lines but also include a test for the random behaviour, you can do this by passing a seed= to the responses_test function: http://axelrod.readthedocs.io/en/latest/tutorials/contributing/strategy/writing_test_for_the_new_strategy.html

Copy link
Member Author

Choose a reason for hiding this comment

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

What exactly is happening here with seed ?
I saw in seed =1 and seed = 2 being passed. What does it do?

Copy link
Member

Choose a reason for hiding this comment

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

So a random process starts with a random seed. This just ensures the "randomness" can be repeated:

>>> import random
>>> random.seed(0)
>>> random.random()
0.8444218515250481
>>> random.seed(0)
0.8444218515250481

The seed=1 and seed=2 just set those seeds for the strategies.