Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""Classes that determine convergence of an algorithm run
2based on population stagnation or max raw score reached"""
3from ase.ga import get_raw_score
6class Convergence:
7 """
8 Base class for all convergence object to be based on.
9 It is necessary to supply the population instance, to be
10 able to obtain current and former populations.
11 """
12 def __init__(self, population_instance):
13 self.pop = population_instance
14 self.pops = {}
16 def converged(self):
17 """This function is called to find out if the algorithm
18 run has converged, it should return True or False.
19 Overwrite this in the inherited class."""
20 raise NotImplementedError
22 def populate_pops(self, to_gen):
23 """Populate the pops dictionary with how the population
24 looked after i number of generations."""
25 for i in range(to_gen):
26 if i not in self.pops.keys():
27 self.pops[i] = self.pop.get_population_after_generation(i)
30class GenerationRepetitionConvergence(Convergence):
31 """Returns True if the latest finished population is stagnated for
32 number_of_generations.
34 Parameters:
36 number_of_generations: int
37 How many generations need to be equal before convergence.
39 number_of_individuals: int
40 How many of the fittest individuals should be included in the
41 convergence test. Default is -1 meaning all in the population.
43 max_generations: int
44 The maximum number of generations the GA is allowed to run.
45 Default is indefinite.
46 """
47 def __init__(self, population_instance, number_of_generations,
48 number_of_individuals=-1, max_generations=100000000):
49 Convergence.__init__(self, population_instance)
50 self.numgens = number_of_generations
51 self.numindis = number_of_individuals
52 self.maxgen = max_generations
54 def converged(self):
55 size = self.pop.pop_size
56 cur_gen_num = self.pop.dc.get_generation_number(size)
58 if cur_gen_num >= self.maxgen:
59 return True
61 if cur_gen_num <= 1:
62 return False
64 cur_pop = self.pop.get_current_population()
65 newest = max([i.info['key_value_pairs']['generation']
66 for i in cur_pop[:self.numindis]])
67 if newest + self.numgens > cur_gen_num:
68 return False
70 self.populate_pops(cur_gen_num)
72 duplicate_gens = 1
73 latest_pop = self.pops[cur_gen_num - 1]
74 for i in range(cur_gen_num - 2, -1, -1):
75 test_pop = self.pops[i]
76 if test_pop[:self.numindis] == latest_pop[:self.numindis]:
77 duplicate_gens += 1
78 if duplicate_gens >= self.numgens:
79 return True
80 return False
83class RawScoreConvergence(Convergence):
84 """Returns True if the supplied max_raw_score has been reached"""
85 def __init__(self, population_instance, max_raw_score, eps=1e-3):
86 Convergence.__init__(self, population_instance)
87 self.max_raw_score = max_raw_score
88 self.eps = eps
90 def converged(self):
91 cur_pop = self.pop.get_current_population()
92 if abs(get_raw_score(cur_pop[0]) - self.max_raw_score) <= self.eps:
93 return True
94 return False
97class NeverConvergence:
98 """Test class that never converges."""
99 def __init__(self):
100 pass
102 def converged(self):
103 return False