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

telemachus
Python Testing With Pytest - Chapter 2, warnings for “unregistered custom marks” While running the smoke tests in Chapter 2, I get these...
New
jesse050717
Title: Web Development with Clojure, Third Edition, pg 116 Hi - I just started chapter 5 and I am stuck on page 116 while trying to star...
New
lirux
Hi Jamis, I think there’s an issue with a test on chapter 6. I own the ebook, version P1.0 Feb. 2019. This test doesn’t pass for me: ...
New
herminiotorres
Hi @Margaret , On page VII the book tells us the example and snippets will be all using Elixir version 1.11 But on page 3 almost the en...
New
alanq
This isn’t directly about the book contents so maybe not the right forum…but in some of the code apps (e.g. turbo/06) it sends a TURBO_ST...
New
swlaschin
The book has the same “Problem space/Solution space” diagram on page 18 as is on page 17. The correct Problem/Solution space diagrams ar...
New
curtosis
Running mix deps.get in the sensor_hub directory fails with the following error: ** (Mix) No SSH public keys found in ~/.ssh. An ssh aut...
New
brunogirin
When installing Cards as an editable package, I get the following error: ERROR: File “setup.py” not found. Directory cannot be installe...
New
jonmac
The allprojects block listed on page 245 produces the following error when syncing gradle: “org.gradle.api.GradleScriptException: A prob...
New
ggerico
I got this error when executing the plot files on macOS Ventura 13.0.1 with Python 3.10.8 and matplotlib 3.6.1: programming_ML/code/03_...
New

Other popular topics Top

AstonJ
Or looking forward to? :nerd_face:
503 15149 280
New
PragmaticBookshelf
Tailwind CSS is an exciting new CSS framework that allows you to design your site by composing simple utility classes to create complex e...
New
Help
I am trying to crate a game for the Nintendo switch, I wanted to use Java as I am comfortable with that programming language. Can you use...
New
AstonJ
If you want a quick and easy way to block any website on your Mac using Little Snitch simply… File &gt; New Rule: And select Deny, O...
New
New
AstonJ
If you’re getting errors like this: psql: error: connection to server on socket “/tmp/.s.PGSQL.5432” failed: No such file or directory ...
New
NewsBot
Node.js v22.14.0 has been released. Link: Release 2025-02-11, Version 22.14.0 'Jod' (LTS), @aduh95 · nodejs/node · GitHub
New
PragmaticBookshelf
As digital systems increasingly run the world, mastery of the recurring patterns of software development risk is the key to fast and effe...
New
xiji2646-netizen
Woke up to this today: Claude Code’s complete source code exposed via npm source map. Not a snippet. All 512,000 lines. 1,900 TypeScript ...
New
xiji2646-netizen
There’s a GitHub repo at forrestchang/andrej-karpathy-skills that’s sitting at 97.8k stars. It’s a single CLAUDE.md file with four behavi...
New

Sub Categories: