~jjmerelo/improving-eas/trunk

29 by Juan J. Merelo
Changes for making user-selectable variables
1
--[[
2
@title Evolutionary algorith
3
@param a chromosome length
4
@default a 16
5
@param b population size
6
@default b 32
7
@param c number of generations
8
@default c 40
9
]]--
10
28 by Juan J. Merelo
GA for the Canon g9 within the CHDK environment
11
-- Create a random chromosome
12
function random_chromosome (length)
13
   chromosome = ''
14
   for i=1,length  do
15
      chromosome = chromosome .. ((math.random(100) > 50) and "1" or "0") 
16
   end
17
   return chromosome
18
end
19
20
-- Compare according to fitness
21
function compare(a,b)
22
   return fitness_of[b] < fitness_of[a]
23
end
24
25
-- Computes maxOnes fitness
26
function compute_fitness (chromosome)
27
   ones = 0
28
   for i=1,chromosome:len() do 
29
      ones = ones + ( (chromosome:sub(i,i) == "1") and 1 or 0 )
30
   end
31
   return ones
32
end
33
34
-- Mutate a single chromosome
35
function mutate ( pool )
36
   for i=1,#pool do
37
      mutation_point = math.random( pool[i]:len() )
38
      temp = pool[i]
39
      pool[i] = temp:sub(1,mutation_point-1)
40
      pool[i] = pool[i] .. temp:sub(mutation_point,mutation_point)
41
      pool[i] = pool[i] .. temp:sub(mutation_point+1,temp:len())
42
   end
43
end
44
45
-- crossover 
46
function crossover ( chrom1, chrom2 )
47
   length = chrom1:len()
48
   xover_point =  math.random ( length - 1 )
49
   range = 1 + math.random ( length - xover_point ) 
50
   new_chrom1 = chrom1:sub(1,xover_point-1)
51
   new_chrom2 = chrom2:sub(1,xover_point-1)
52
   new_chrom1 = new_chrom1 .. chrom2:sub(xover_point,xover_point+range)
53
   new_chrom2 = new_chrom2 .. chrom1:sub(xover_point,xover_point+range)
54
   new_chrom1 = new_chrom1 .. chrom1:sub(xover_point+range+1,length)
55
   new_chrom2 = new_chrom2 .. chrom2:sub(xover_point+range+1,length)
56
   return new_chrom1, new_chrom2
57
end
58
59
-- Here goes the program
60
29 by Juan J. Merelo
Changes for making user-selectable variables
61
chromosome_length = a;
62
population_size = b;
63
generations =  c;
28 by Juan J. Merelo
GA for the Canon g9 within the CHDK environment
64
65
math.randomseed( os.time() ) -- true randomness
66
67
population = {};
68
for i=1,population_size do 
69
    population[i] = random_chromosome( chromosome_length )
70
end
71
72
fitness_of = {}
73
best = {}
74
this_generation = 0
75
76
logfile=io.open("A/paramdmp.log","wb")
77
while (this_generation <= generations ) do 
78
   total_fitness = 0;
79
   print( "Generation "..this_generation )
80
   for i=1,population_size do
81
      if ( fitness_of[population[i]] == nil ) then
82
	 fitness_of[population[i]] = compute_fitness( population[i] )
83
      end
84
      total_fitness = total_fitness + fitness_of[population[i]]
85
   end
86
   table.sort( population, compare )
87
88
--[[   for i,value in ipairs(population) do
89
      key = table.concat( value )
90
      print(key,": ",fitness_of[key])
91
   end
92
]]--
93
94
   for i=1,2 do
95
      best[i] = population[i]  -- keep for later
96
   end
97
   print(  best[1] )
98
   logfile:write(  best[1].."\n" )
99
   if (fitness_of[best[1]] >= chromosome_length ) then
100
      break
101
   end
102
103
   pool = {}
104
   index = 0
105
   while #pool < population_size do
106
      first = population[ math.random(#population)]
107
      second = population[ math.random(#population)]
108
109
      if ( fitness_of[first] > fitness_of[second] ) then
110
	 pool[#pool+1] = first
111
      else
112
	 pool[#pool+1] = second
113
      end
114
   end
115
   population = {} -- reset population
116
   for i = 1,population_size/2-1 do
117
      first = pool[math.random(#pool)];
118
      second = pool[math.random(#pool)];
119
      first_prime, second_prime = crossover( first, second)
120
      population[#population+1] = first_prime
121
      population[#population+1] = second_prime
122
   end
123
   mutate( population )
124
   population[#population+1] = best[1]
125
   population[#population+1] = best[2]
126
   this_generation = this_generation + 1
127
end
128
129
logfile:close()