-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcustom_species_set.py
95 lines (79 loc) · 3.88 KB
/
custom_species_set.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
from neat.math_util import mean, stdev
from neat.six_util import iteritems, iterkeys, itervalues
from neat.species import DefaultSpeciesSet, GenomeDistanceCache, Species
class CustomSpeciesSet(DefaultSpeciesSet):
def speciate(self, config, population, generation):
print("speciating");
"""
Place genomes into species by genetic similarity.
Note that this method assumes the current representatives of the species are from the old
generation, and that after speciation has been performed, the old representatives should be
dropped and replaced with representatives from the new generation. If you violate this
assumption, you should make sure other necessary parts of the code are updated to reflect
the new behavior.
"""
assert isinstance(population, dict)
compatibility_threshold = self.species_set_config.compatibility_threshold
# Find the best representatives for each existing species.
unspeciated = set(iterkeys(population))
distances = GenomeDistanceCache(config.genome_config)
new_representatives = {}
new_members = {}
for sid, s in iteritems(self.species):
candidates = []
for gid in unspeciated:
g = population[gid]
d = distances(s.representative, g)
candidates.append((d, g))
# The new representative is the genome closest to the current representative.
ignored_rdist, new_rep = min(candidates, key=lambda x: x[0])
new_rid = new_rep.key
new_representatives[sid] = new_rid
new_members[sid] = [new_rid]
unspeciated.remove(new_rid)
## NEW IMPLEMENTATION: Calculate representative variation to use the "relative" distance
reps = set(itervalues(new_representatives));
rep_distances = {};
while reps:
rid = reps.pop();
r = population[rid];
for oid in reps:
rep_distances[(rid,oid)] = distances(r,population[oid]);
rep_stdev = stdev(itervalues(distances.distances));
self.reporters.info(f'Representative genetic distance (stdev): {rep_stdev}');
# Partition population into species based on genetic similarity.
while unspeciated:
gid = unspeciated.pop()
g = population[gid]
# Find the species with the most similar representative.
candidates = []
for sid, rid in iteritems(new_representatives):
rep = population[rid]
d = distances(rep, g)
if d < compatibility_threshold*rep_stdev:
candidates.append((d, sid))
if candidates:
ignored_sdist, sid = min(candidates, key=lambda x: x[0])
new_members[sid].append(gid)
else:
# No species is similar enough, create a new species, using
# this genome as its representative.
sid = next(self.indexer)
new_representatives[sid] = gid
new_members[sid] = [gid]
# Update species collection based on new speciation.
self.genome_to_species = {}
for sid, rid in iteritems(new_representatives):
s = self.species.get(sid)
if s is None:
s = Species(sid, generation)
self.species[sid] = s
members = new_members[sid]
for gid in members:
self.genome_to_species[gid] = sid
member_dict = dict((gid, population[gid]) for gid in members)
s.update(population[rid], member_dict)
gdmean = mean(itervalues(distances.distances))
gdstdev = stdev(itervalues(distances.distances))
self.reporters.info(
'Mean genetic distance {0:.3f}, standard deviation {1:.3f}'.format(gdmean, gdstdev))