eekenpiet

eekenpiet

Genetic Algorithms in Elixir: Chapter 9/10 ebook-1.0.2 Genealogy not working well

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

def crossover(population, problem, opts \\ []) do
................
................

        c1 = %Chromosome{
          c1
          | id: Base.encode16(:crypto.strong_rand_bytes(64)),
            fitness: problem.fitness_function(c1)
        }

        c2 = %Chromosome{
          c2
          | id: Base.encode16(:crypto.strong_rand_bytes(64)),
            fitness: problem.fitness_function(c2)
        }

        Utilities.Genealogy.add_chromosome(p1, p2, c1)
        Utilities.Genealogy.add_chromosome(p1, p2, c2)
        [c1 | [c2 | acc]]

and of mutation():

def mutation(population, problem, opts \\ []) do
.......
.......
      mutant = %Chromosome{
        mutant
        | id: Base.encode16(:crypto.strong_rand_bytes(64)),
          fitness: problem.fitness_function(mutant)
      }

      Utilities.Genealogy.add_chromosome(c, mutant)
      mutant

I did use the following tiger_simulation, and watch the change in genotype:

defmodule TigerSimulation do
  @behaviour Problem
  alias Types.Chromosome

 @impl true
  def genotype do
    genes = for _ <- 1..8, do: Enum.random(0..1)
    chromo = %Chromosome{genes: genes, size: 8, id: Base.encode16(:crypto.strong_rand_bytes(64))}
    fitness = fitness_function(chromo)
    %Chromosome{chromo | fitness: fitness}
  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]) #staat in hoofd-directory
:ok = IO.binwrite(dotfile, dot)
:ok = File.close(dotfile)

and in evolve()

 ........
 .......
 children = crossover(parents, problem, opts)
 ......
 mutants = mutation(population, problem, opts)

Tip: In Intellij Idea you have a nice plugin for .dot files: Dot plus!
If selection <1 you wil see also loose nodes. Nice!

And some other suggestions:

 def run(problem, opts \\ []) do
    population = initialize(&problem.genotype/0, opts)
    start_bestfitness = %Chromosome{hd(population) | fitness: 0.0}

    population
    |> evolve(problem, 0, start_bestfitness, bestgeneration = 0, opts)
  end
  
def evolve(population, problem, generation, bestfitness, bestgeneration, opts \\ []) do
    population = evaluate(population, &problem.fitness_function/1, opts)

    best = hd(population)
    best1 = best.fitness
    best2 = bestfitness.fitness

    bestfitness =
      if best1 > best2 do
        best
      else
        bestfitness
      end

    bestgeneration =
      if best1 > best2 do
        generation
      else
        bestgeneration
      end

    IO.inspect(best, label: "\n\ncurrent best:")
    IO.write("Generation: #{generation}")
    statistics(population, generation, opts)

    if problem.terminate?(population, generation) do
............................
.............................
    

Where Next?

Popular Pragmatic Bookshelf topics Top

edruder
I thought that there might be interest in using the book with Rails 6.1 and Ruby 2.7.2. I’ll note what I needed to do differently here. ...
New
joepstender
The generated iex result below should list products instead of product for the metadata. (page 67) iex&gt; product = %Product{} %Pento....
New
gilesdotcodes
In case this helps anyone, I’ve had issues setting up the rails source code. Here were the solutions: In Gemfile, change gem 'rails' t...
New
New
Charles
In general, the book isn’t yet updated for Phoenix version 1.6. On page 18 of the book, the authors indicate that an auto generated of ro...
New
New
AufHe
I’m a newbie to Rails 7 and have hit an issue with the bin/Dev script mentioned on pages 112-113. Iteration A1 - Seeing the list of prod...
New
NaplesDave
@mfazio23 I am following along and I have gotten up to adding the data binding items. The project has built alright until I added the da...
New
mcpierce
@mfazio23 I’ve applied the changes from Chapter 5 of the book and everything builds correctly and runs. But, when I try to start a game,...
New
dachristenson
I just bought this book to learn about Android development, and I’m already running into a major issue in Ch. 1, p. 20: “Update activity...
New

Other popular topics Top

PragmaticBookshelf
Take your Go skills to the next level by learning how to design, develop, and deploy a distributed service. Start from the bare essential...
New
PragmaticBookshelf
Learn from the award-winning programming series that inspired the Elixir language, and go on a step-by-step journey through the most impo...
New
Exadra37
Please tell us what is your preferred monitor setup for programming(not gaming) and why you have chosen it. Does your monitor have eye p...
New
brentjanderson
Bought the Moonlander mechanical keyboard. Cherry Brown MX switches. Arms and wrists have been hurting enough that it’s time I did someth...
New
AstonJ
Curious to know which languages and frameworks you’re all thinking about learning next :upside_down_face: Perhaps if there’s enough peop...
New
Rainer
My first contact with Erlang was about 2 years ago when I used RabbitMQ, which is written in Erlang, for my job. This made me curious and...
New
PragmaticBookshelf
Build highly interactive applications without ever leaving Elixir, the way the experts do. Let LiveView take care of performance, scalabi...
New
PragmaticBookshelf
Author Spotlight Rebecca Skinner @RebeccaSkinner Welcome to our latest author spotlight, where we sit down with Rebecca Skinner, auth...
New
New
First poster: AstonJ
Jan | Rethink the Computer. Jan turns your computer into an AI machine by running LLMs locally on your computer. It’s a privacy-focus, l...
New

Sub Categories: