Skip to content

Commit 174352b

Browse files
committed
Substitution tests for evolvable players
1 parent 87b33b9 commit 174352b

File tree

9 files changed

+322
-196
lines changed

9 files changed

+322
-196
lines changed

axelrod/moran.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
"""Implementation of the Moran process on Graphs."""
22

3-
from collections import Counter
43
import random
5-
from random import randrange
4+
from collections import Counter
65
from typing import Callable, List, Optional, Set, Tuple
76

87
import matplotlib.pyplot as plt
@@ -12,6 +11,7 @@
1211
from .deterministic_cache import DeterministicCache
1312
from .graph import Graph, complete_graph
1413
from .match import Match
14+
from .random_ import randrange
1515

1616

1717
def fitness_proportionate_selection(

axelrod/random_.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,12 @@ def random_flip(action: Action, threshold: float) -> Action:
6363
return action
6464

6565

66-
# def randrange(a: int, b: int) -> int:
67-
# """Python 2 / 3 compatible randrange. Returns a random integer uniformly
68-
# between a and b (inclusive)"""
69-
# c = b - a
70-
# r = c * random.random()
71-
# return a + int(r)
66+
def randrange(a: int, b: int) -> int:
67+
"""Python 2 / 3 compatible randrange. Returns a random integer uniformly
68+
between a and b (inclusive)"""
69+
c = b - a
70+
r = c * random.random()
71+
return a + int(r)
7272

7373

7474
def random_vector(size):

axelrod/tests/strategies/test_ann.py

Lines changed: 57 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from axelrod.load_data_ import load_weights
77
from axelrod.strategies.ann import split_weights
88
from .test_player import TestPlayer
9-
from .test_evolvable_player import TestEvolvablePlayer
9+
from .test_evolvable_player import PartialClass, TestEvolvablePlayer
1010

1111

1212
C, D = axelrod.Action.C, axelrod.Action.D
@@ -23,43 +23,6 @@ def test_split_weights(self):
2323
split_weights([0] * 12, 10, 1)
2424

2525

26-
class TestEvolvableANN(unittest.TestCase):
27-
28-
player_class = axelrod.EvolvableANN
29-
30-
def test_normalized_parameters(self):
31-
# Must specify at least one of cycle or cycle_length
32-
self.assertRaises(
33-
InsufficientParametersError,
34-
self.player_class._normalize_parameters
35-
)
36-
self.assertRaises(
37-
InsufficientParametersError,
38-
self.player_class._normalize_parameters,
39-
weights=nn_weights["Evolved ANN 5"][2]
40-
)
41-
42-
43-
class TestEvolvableANN2(TestEvolvablePlayer):
44-
name = "EvolvableANN"
45-
player_class = axelrod.EvolvableANN
46-
parent_class = axelrod.ANN
47-
parent_kwargs = ["num_features", "num_hidden", "weights"]
48-
init_parameters = {"num_features": 17, "num_hidden": 8}
49-
50-
51-
class TestEvolvableANN3(TestEvolvablePlayer):
52-
name = "EvolvableANN"
53-
player_class = axelrod.EvolvableANN
54-
parent_class = axelrod.ANN
55-
parent_kwargs = ["num_features", "num_hidden", "weights"]
56-
init_parameters = {
57-
"num_features": nn_weights["Evolved ANN 5"][0],
58-
"num_hidden": nn_weights["Evolved ANN 5"][1],
59-
"weights": nn_weights["Evolved ANN 5"][2]
60-
}
61-
62-
6326
class TestEvolvedANN(TestPlayer):
6427

6528
name = "Evolved ANN"
@@ -127,3 +90,59 @@ def test_strategy(self):
12790

12891
actions = [(C, D), (D, D), (D, D)]
12992
self.versus_test(axelrod.Defector(), expected_actions=actions)
93+
94+
95+
class TestEvolvableANN(unittest.TestCase):
96+
97+
player_class = axelrod.EvolvableANN
98+
99+
def test_normalized_parameters(self):
100+
# Must specify at least one of cycle or cycle_length
101+
self.assertRaises(
102+
InsufficientParametersError,
103+
self.player_class._normalize_parameters
104+
)
105+
self.assertRaises(
106+
InsufficientParametersError,
107+
self.player_class._normalize_parameters,
108+
weights=nn_weights["Evolved ANN 5"][2]
109+
)
110+
111+
112+
class TestEvolvableANN2(TestEvolvablePlayer):
113+
name = "EvolvableANN"
114+
player_class = axelrod.EvolvableANN
115+
parent_class = axelrod.ANN
116+
parent_kwargs = ["num_features", "num_hidden", "weights"]
117+
init_parameters = {"num_features": 17, "num_hidden": 8}
118+
119+
120+
class TestEvolvableANN3(TestEvolvablePlayer):
121+
name = "EvolvableANN"
122+
player_class = axelrod.EvolvableANN
123+
parent_class = axelrod.ANN
124+
parent_kwargs = ["num_features", "num_hidden", "weights"]
125+
init_parameters = {
126+
"num_features": nn_weights["Evolved ANN 5"][0],
127+
"num_hidden": nn_weights["Evolved ANN 5"][1],
128+
"weights": nn_weights["Evolved ANN 5"][2]
129+
}
130+
131+
132+
# Substitute EvolvableANN as a regular EvolvedANN5.
133+
EvolvableANNPlayerWithDefault = PartialClass(
134+
axelrod.EvolvableANN,
135+
num_features=num_features,
136+
num_hidden=num_hidden,
137+
weights=weights
138+
)
139+
140+
141+
class EvolvableANNAsANN(TestEvolvedANN5):
142+
player = EvolvableANNPlayerWithDefault
143+
144+
def test_equality_of_clone(self):
145+
pass
146+
147+
def test_equality_of_pickle_clone(self):
148+
pass

axelrod/tests/strategies/test_cycler.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from axelrod.evolvable_player import InsufficientParametersError
1111

1212
from .test_player import TestPlayer
13-
from .test_evolvable_player import TestEvolvablePlayer
13+
from .test_evolvable_player import PartialClass, TestEvolvablePlayer
1414

1515
C, D = Action.C, Action.D
1616

@@ -216,3 +216,15 @@ class TestEvolvableCycler3(TestEvolvablePlayer):
216216
"mutation_potency": 10}
217217

218218

219+
# Substitute EvolvedCycler as a regular Cycler.
220+
EvolvableCyclerWithDefault = PartialClass(EvolvableCycler, cycle="CCD")
221+
222+
223+
class EvolvableCyclerAsCycler(TestBasicCycler):
224+
player = EvolvableCyclerWithDefault
225+
226+
def test_equality_of_clone(self):
227+
pass
228+
229+
def test_equality_of_pickle_clone(self):
230+
pass

axelrod/tests/strategies/test_evolvable_player.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import functools
12
import random
23
import unittest
34

@@ -10,6 +11,15 @@
1011
C, D = Action.C, Action.D
1112

1213

14+
def PartialClass(cls, **kwargs):
15+
16+
class PartialedClass(cls):
17+
__init__ = functools.partialmethod(
18+
cls.__init__, **kwargs)
19+
20+
return PartialedClass
21+
22+
1323
class EvolvableTestOpponent(EvolvablePlayer):
1424
name = "EvolvableTestOpponent"
1525

axelrod/tests/strategies/test_finite_state_machines.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from axelrod.strategies.finite_state_machines import EvolvableFSMPlayer, FSMPlayer, SimpleFSM
99

1010
from .test_player import TestPlayer
11-
from .test_evolvable_player import TestEvolvablePlayer
11+
from .test_evolvable_player import PartialClass, TestEvolvablePlayer
1212

1313
C, D = axelrod.Action.C, axelrod.Action.D
1414

@@ -1114,3 +1114,21 @@ class TestEvolvableFSMPlayer4(TestEvolvablePlayer):
11141114
"initial_state": 1,
11151115
"initial_action": C
11161116
}
1117+
1118+
1119+
# Substitute EvolvedFSMPlayer as a regular FSMPlayer.
1120+
EvolvableFSMPlayerWithDefault = PartialClass(
1121+
EvolvableFSMPlayer,
1122+
transitions=((1, C, 1, C), (1, D, 1, D)),
1123+
initial_state=1,
1124+
initial_action=C)
1125+
1126+
1127+
class EvolvableFSMAsFSM(TestFSMPlayer):
1128+
player = EvolvableFSMPlayerWithDefault
1129+
1130+
def test_equality_of_clone(self):
1131+
pass
1132+
1133+
def test_equality_of_pickle_clone(self):
1134+
pass

axelrod/tests/strategies/test_gambler.py

Lines changed: 88 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -5,77 +5,15 @@
55
import random
66
import unittest
77
import axelrod
8+
from axelrod.load_data_ import load_pso_tables
89
from axelrod.strategies.lookerup import create_lookup_table_keys
910
from .test_lookerup import convert_original_to_current
1011
from .test_player import TestPlayer
11-
from .test_evolvable_player import TestEvolvablePlayer
12+
from .test_evolvable_player import PartialClass, TestEvolvablePlayer
1213

13-
C, D = axelrod.Action.C, axelrod.Action.D
14-
15-
16-
class TestEvolvableGambler(unittest.TestCase):
17-
18-
def test_receive_vector(self):
19-
plays, op_plays, op_start_plays = 1, 1, 1
20-
player = axelrod.EvolvableGambler(
21-
parameters=(plays, op_plays, op_start_plays))
2214

23-
self.assertRaises(AttributeError, axelrod.EvolvableGambler.__getattribute__,
24-
*[player, 'vector'])
25-
26-
vector = [random.random() for _ in range(8)]
27-
player.receive_vector(vector)
28-
self.assertEqual(player.pattern, vector)
29-
30-
def test_vector_to_instance(self):
31-
plays, op_plays, op_start_plays = 1, 1, 1
32-
player = axelrod.EvolvableGambler(
33-
parameters=(plays, op_plays, op_start_plays))
34-
35-
vector = [random.random() for _ in range(8)]
36-
player.receive_vector(vector)
37-
keys = create_lookup_table_keys(player_depth=plays, op_depth=op_plays,
38-
op_openings_depth=op_start_plays)
39-
action_dict = dict(zip(keys, vector))
40-
self.assertEqual(player._lookup.dictionary, action_dict)
41-
42-
def test_create_vector_bounds(self):
43-
plays, op_plays, op_start_plays = 1, 1, 1
44-
player = axelrod.EvolvableGambler(
45-
parameters=(plays, op_plays, op_start_plays))
46-
lb, ub = player.create_vector_bounds()
47-
self.assertIsInstance(lb, list)
48-
self.assertIsInstance(ub, list)
49-
self.assertEqual(len(lb), 8)
50-
self.assertEqual(len(ub), 8)
51-
52-
53-
class TestEvolvableGambler2(TestEvolvablePlayer):
54-
name = "EvolvableGambler"
55-
player_class = axelrod.EvolvableGambler
56-
parent_class = axelrod.Gambler
57-
parent_kwargs = ["lookup_dict"]
58-
init_parameters = {"parameters": (1, 1, 1),
59-
"initial_actions": (C,)}
60-
61-
62-
class TestEvolvableGambler3(TestEvolvablePlayer):
63-
name = "EvolvableGambler"
64-
player_class = axelrod.EvolvableGambler
65-
parent_class = axelrod.Gambler
66-
parent_kwargs = ["lookup_dict"]
67-
init_parameters = {"parameters": (3, 2, 1),
68-
"initial_actions": (C, C, C,)}
69-
70-
71-
class TestEvolvableGambler4(TestEvolvablePlayer):
72-
name = "EvolvableGambler"
73-
player_class = axelrod.EvolvableGambler
74-
parent_class = axelrod.Gambler
75-
parent_kwargs = ["lookup_dict"]
76-
init_parameters = {"parameters": (2, 2, 2),
77-
"pattern": [random.random() for _ in range(64)],
78-
"initial_actions": (C, C,)}
15+
tables = load_pso_tables("pso_gambler.csv", directory="data")
16+
C, D = axelrod.Action.C, axelrod.Action.D
7917

8018

8119
class TestGambler(TestPlayer):
@@ -553,3 +491,87 @@ def test_vs_alternator(self):
553491
new_seed = 1
554492
expected = [(C, C), (C, D), (C, C), (D, D), (D, C), (C, D), (D, C)]
555493
self.versus_test(axelrod.Alternator(), expected_actions=expected, seed=new_seed)
494+
495+
496+
class TestEvolvableGambler(unittest.TestCase):
497+
498+
def test_receive_vector(self):
499+
plays, op_plays, op_start_plays = 1, 1, 1
500+
player = axelrod.EvolvableGambler(
501+
parameters=(plays, op_plays, op_start_plays))
502+
503+
self.assertRaises(AttributeError, axelrod.EvolvableGambler.__getattribute__,
504+
*[player, 'vector'])
505+
506+
vector = [random.random() for _ in range(8)]
507+
player.receive_vector(vector)
508+
self.assertEqual(player.pattern, vector)
509+
510+
def test_vector_to_instance(self):
511+
plays, op_plays, op_start_plays = 1, 1, 1
512+
player = axelrod.EvolvableGambler(
513+
parameters=(plays, op_plays, op_start_plays))
514+
515+
vector = [random.random() for _ in range(8)]
516+
player.receive_vector(vector)
517+
keys = create_lookup_table_keys(player_depth=plays, op_depth=op_plays,
518+
op_openings_depth=op_start_plays)
519+
action_dict = dict(zip(keys, vector))
520+
self.assertEqual(player._lookup.dictionary, action_dict)
521+
522+
def test_create_vector_bounds(self):
523+
plays, op_plays, op_start_plays = 1, 1, 1
524+
player = axelrod.EvolvableGambler(
525+
parameters=(plays, op_plays, op_start_plays))
526+
lb, ub = player.create_vector_bounds()
527+
self.assertIsInstance(lb, list)
528+
self.assertIsInstance(ub, list)
529+
self.assertEqual(len(lb), 8)
530+
self.assertEqual(len(ub), 8)
531+
532+
533+
class TestEvolvableGambler2(TestEvolvablePlayer):
534+
name = "EvolvableGambler"
535+
player_class = axelrod.EvolvableGambler
536+
parent_class = axelrod.Gambler
537+
parent_kwargs = ["lookup_dict"]
538+
init_parameters = {"parameters": (1, 1, 1),
539+
"initial_actions": (C,)}
540+
541+
542+
class TestEvolvableGambler3(TestEvolvablePlayer):
543+
name = "EvolvableGambler"
544+
player_class = axelrod.EvolvableGambler
545+
parent_class = axelrod.Gambler
546+
parent_kwargs = ["lookup_dict"]
547+
init_parameters = {"parameters": (3, 2, 1),
548+
"initial_actions": (C, C, C,)}
549+
550+
551+
class TestEvolvableGambler4(TestEvolvablePlayer):
552+
name = "EvolvableGambler"
553+
player_class = axelrod.EvolvableGambler
554+
parent_class = axelrod.Gambler
555+
parent_kwargs = ["lookup_dict"]
556+
init_parameters = {"parameters": (2, 2, 2),
557+
"pattern": [random.random() for _ in range(64)],
558+
"initial_actions": (C, C,)}
559+
560+
561+
# Substitute EvolvableHMMPlayer as a regular HMMPlayer.
562+
EvolvableGamblerWithDefault = PartialClass(
563+
axelrod.EvolvableGambler,
564+
pattern=tables[("PSO Gambler 2_2_2", 2, 2, 2)],
565+
parameters=(2, 2, 2),
566+
initial_actions=(C,C,)
567+
)
568+
569+
570+
class EvolvableGamblerAsGambler(TestPSOGambler2_2_2):
571+
player = EvolvableGamblerWithDefault
572+
573+
def test_equality_of_clone(self):
574+
pass
575+
576+
def test_equality_of_pickle_clone(self):
577+
pass

0 commit comments

Comments
 (0)