Xavier Nayrac

Accro au TDD, rubyiste mais pas que, maker, heureux utilisateur de Vim, accordéoniste.
Si vous vous sentez particulièrement généreux, suivez moi sur Twitter.

Un algorithme génétique en Julia - partie 16

| Comments

Niveau : intermédiaire

J’ai retiré les nombres magiques et renommé les quelques variables qui étaient abrégées. Puis j’ai voulu commencer à documenter le code. Là je me suis aperçu que le typage était une bonne façon de documenter Julia. Par exemple:

1
2
3
type Chromosome
  genes::Array{Int}
end

m’apparait quasiment comme étant auto-documenté, comparé à la version précédente:

1
2
3
type Chromosome
  genes
end

Plus de documentation plus tard, quand j’aurais trouvé si il y a un standard en Julia (j’ai bien l’impression qu’il n’y en a pas :( ).

Pour l’instant, voici le code après son enième remaniement:

main.jl
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
type Chromosome
  genes::Array{Int}
end

create_genes(size) = rand(0:1, size)

function create_population(size, chromosome_size)
  [ Chromosome(create_genes(chromosome_size)) for _ in 1:size ]
end

score(population) = map(chromosome -> sum(chromosome.genes), population)

function fight(scores, index1, index2, rate)
  if rand() < rate
    scores[index1] > scores[index2] ? index1 : index2
  else
    scores[index1] > scores[index2] ? index2 : index1
  end
end

function tournament(scores, rate)
  population_size = length(scores)
  selection_size = population_size * 2
  [ fight(scores, rand(1:population_size), rand(1:population_size), rate)
    for _ in 1:selection_size ]
end

function crossover(chromosome1, chromosome2, population_size)
  cut_point = rand(1:length(chromosome1.genes))
  first_part = chromosome1.genes[1:cut_point]
  second_part = chromosome2.genes[cut_point + 1:end]
  mutate(Chromosome([ first_part, second_part]), population_size)
end

function reproduction(new_population, current_population, selection,
                      population_size)
  if selection == []
    return new_population
  else
    father = current_population[selection[1]]
    mother = current_population[selection[2]]
    child = crossover(father, mother, population_size)
    reproduction([new_population, child], current_population, selection[3:end],
                 population_size)
  end
end

function mutate(chromosome, population_size)
  mutator(gene) = if rand(1:population_size) == 1
    gene == 1 ? 0 : 1
  else
    gene
  end
  Chromosome([ mutator(gene) for gene in chromosome.genes ])
end

function run(population_size, genes_size, generations, fight_rate)
  current = create_population(population_size, genes_size)
  for i in 1:generations
    scores = score(current)
    best = maximum(scores)
    println("Generation $i Best $best")
    selection = tournament(scores, fight_rate)
    current = reproduction([], current, selection, population_size)
  end
end

À demain.

Articles connexes

Commentaires