Chapter 9/10 ebook-1.02 Genealogy not working well.
As already mentioned in one of the errata the ID of every chromosome is the same.
So plotting the tree with libgraph gives many problems.
For instance parents are not unique, they are all inserted.
I did change a few things. Nodes are now unique.
Labels are much smaller, because I changed them to fitness.
You now get a nice plot with small nodes.
This is the relevant part of genealogy.ex:
def handle_cast({:add_chromosome, parent, child}, genealogy) do
new_genealogy =
genealogy
|> Graph.add_vertex(child.id, child.fitness)
|> Graph.add_edge(parent.id, child.id)
{:noreply, new_genealogy}
end
def handle_cast({:add_chromosome, parent_a, parent_b, child}, genealogy) do
new_genealogy =
genealogy
|> Graph.add_vertex(child.id, child.fitness)
|> Graph.add_edge(parent_a.id, child.id)
|> Graph.add_edge(parent_b.id, child.id)
{:noreply, new_genealogy}
end
The last part of crossover().
ID’s are now unique. Fitness are assigned
c1 = %Chromosome{
c1
| id: Base.encode16(:crypto.strong_rand_bytes(64)),
fitness: Enum.sum(c1.genes)
}
c2 = %Chromosome{
c2
| id: Base.encode16(:crypto.strong_rand_bytes(64)),
fitness: Enum.sum(c2.genes)
}
Utilities.Genealogy.add_chromosome(p1, p2, c1)
Utilities.Genealogy.add_chromosome(p1, p2, c2)
[c1 | [c2 | acc]]
I did use the following tiger_simulation:
defmodule TigerSimulation do
@behaviour Problem
alias Types.Chromosome
@impl true
def genotype do
genes = for _ <- 1..8, do: Enum.random(0..1)
%Chromosome{genes: genes, size: 8, fitness: Enum.sum(genes), id: Base.encode16(:crypto.strong_rand_bytes(64))}
end
@impl true
def fitness_function(chromosome) do
tropic_scores = [0.0, 3.0, 2.0, 1.0, 0.5, 1.0, -1.0, 0.0]
# tundra_scores = [1.0, 3.0, -2.0, -1.0, 0.5, 2.0, 1.0, 0.0]
traits = chromosome.genes
traits
|> Enum.zip(tropic_scores)
|> Enum.map(fn {t, s} -> t * s end)
|> Enum.sum()
end
@impl true
def terminate?(_population, generation), do: generation == 10
end
_tiger =
Genetic.run(TigerSimulation,
population_size: 8,
selection_rate: 0.8,
mutation_rate: 0.1
)
genealogy = Utilities.Genealogy.get_tree()
{:ok, dot} = Graph.Serializers.DOT.serialize(genealogy)
{:ok, dotfile} = File.open("tiger_simulation.dot", [:write])
:ok = IO.binwrite(dotfile, dot)
:ok = File.close(dotfile)
Tip: In Intellij Idea you have a nice plugin for .dot files: Dot plus!
If selection <1 you wil see also loose nodes. Nice!