Hide keyboard shortcuts

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 

4 

5 

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 = {} 

15 

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 

21 

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) 

28 

29 

30class GenerationRepetitionConvergence(Convergence): 

31 """Returns True if the latest finished population is stagnated for 

32 number_of_generations. 

33 

34 Parameters: 

35 

36 number_of_generations: int 

37 How many generations need to be equal before convergence. 

38 

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. 

42 

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 

53 

54 def converged(self): 

55 size = self.pop.pop_size 

56 cur_gen_num = self.pop.dc.get_generation_number(size) 

57 

58 if cur_gen_num >= self.maxgen: 

59 return True 

60 

61 if cur_gen_num <= 1: 

62 return False 

63 

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 

69 

70 self.populate_pops(cur_gen_num) 

71 

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 

81 

82 

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 

89 

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 

95 

96 

97class NeverConvergence: 

98 """Test class that never converges.""" 

99 def __init__(self): 

100 pass 

101 

102 def converged(self): 

103 return False