Xavier Nayrac

Rubyiste accro au TDD, serial blogger, apprenti data scientist, 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 10

| Comments

Niveau : intermédiaire

Voici le nouveau code de l’algorithme:

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
type Chromosome
  genes
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(x -> sum(x.genes), population)

function fight(scores, index1, index2)
  scores[index1] > scores[index2] ? index1 : index2
end

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

function crossover(chromosome1, chromosome2)
  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]))
end

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

function mutate(ch)
  mutator(g) = if rand(1:10) == 1
    g == 1 ? 0 : 1
  else
    g
  end
  Chromosome([ mutator(x) for x in ch.genes ])
end

J’ai simplement ajouter la fonction mutate dans crossover:

1
2
3
4
5
6
function crossover(chromosome1, chromosome2)
  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]))
end

Et ça fonctionne:

julia> include("main.jl")

julia> pop = create_population(8, 20)
8-element Array{Chromosome,1}:
 Chromosome([0,0,0,1,1,1,0,0,0,0,0,1,1,0,1,1,0,1,0,1])
 Chromosome([1,0,1,1,0,0,0,0,1,1,0,1,1,0,1,0,1,0,1,1])
 Chromosome([1,0,1,1,1,0,1,0,0,0,1,0,0,1,0,1,0,0,0,1])
 Chromosome([1,1,1,1,1,0,0,0,0,0,1,1,0,1,1,0,1,0,0,1])
 Chromosome([0,1,1,0,0,0,0,0,0,1,1,1,0,1,0,0,1,0,1,0])
 Chromosome([0,1,0,1,1,0,0,1,0,0,1,1,1,1,0,0,0,0,0,1])
 Chromosome([1,1,1,0,0,0,1,1,0,1,1,0,0,0,1,1,1,0,0,0])
 Chromosome([1,0,0,0,1,0,0,1,0,1,0,1,0,0,0,0,1,0,0,0])

julia> scores = score(pop)
8-element Array{Int32,1}:
  9
 11
  9
 11
  8
  9
 10
  6

julia> selection = tournament(scores)
16-element Array{Int32,1}:
 7
 7
 7
 7
 ...
 4
 1
 1

julia> gen2 = reproduction([], pop, selection)
8-element Array{Chromosome,1}:
 Chromosome({1,1,1,0,0,0,1,1,0,1,1,0,1,0,1,1,1,0,0,0})
 Chromosome({1,1,1,0,0,0,1,0,0,1,1,0,0,0,1,1,0,0,0,0})
 Chromosome({0,1,0,0,1,0,0,1,0,1,1,1,1,0,1,0,1,0,1,1})
 Chromosome({1,0,1,0,0,1,0,0,1,1,1,1,0,1,0,0,1,0,1,1})
 Chromosome({1,0,1,1,0,0,0,0,1,0,0,1,1,0,1,1,0,0,0,1})
 Chromosome({1,1,1,1,1,1,0,0,0,0,1,1,0,1,1,1,1,0,0,0})
 Chromosome({0,1,1,0,0,0,1,0,0,0,1,1,0,1,1,0,1,0,0,1})
 Chromosome({0,0,0,1,1,1,0,0,0,1,0,1,1,0,1,1,0,1,0,1})

Mais un truc me dérange toujours, le tableau est modifié après passage dans mutate:

julia> c = chromosome(create_genes(10))
chromosome([0,0,0,1,1,1,1,1,0,1])

julia> d = mutate(c)
Chromosome({0,0,0,1,1,1,1,1,0,1})

julia> c.genes
10-element Array{Int32,1}:
...

julia> d.genes
10-element Array{Any,1}:
...

C’est bien ça, le tableau n’est pas du même type. Bon, ça ne dérange pas l’algorithme et c’est l’occasion d’un prochain article sur Julia ;)

À demain.

Articles connexes

Commentaires