genetic

genetic algorithm framework
git clone [email protected]:dracuxan/genetic.git
Log | Files | Refs | README

tiger_sim.exs (3165B)


      1 defmodule TigerSimulation do
      2   alias Types.Chromosome
      3   @behaviour Problem
      4   @traits 8
      5 
      6   # representing tiger genotype: 
      7   #
      8   # | traits           | 0          | 1          |
      9   # +------------------+------------+------------+
     10   # | size             | smaller    | larger     |
     11   # | swimming ability | low        | high       |
     12   # | fur color        | light      | dark       |
     13   # | fat stores       | less       | more       |
     14   # | activity period  | diurnal    | nocturnal  |
     15   # | hunting range    | smaller    | larger     |
     16   # | fur thickness    | less thick | more thick |
     17   # | tail length      | smaller    | larger     |
     18 
     19   @impl true
     20   def genotype do
     21     genes = Enum.map(1..@traits, fn _ -> Enum.random(0..1) end)
     22     %Chromosome{genes: genes, size: @traits}
     23   end
     24 
     25   # scores for each trait: 
     26   #
     27   # | traits           | tropical | tundra |
     28   # +------------------+----------+--------+
     29   # | size             | 0.0      | 1.0    |
     30   # | swimming ability | 3.0      | 3.0    |
     31   # | fur color        | 2.0      | -2.0   |
     32   # | fat stores       | -1.0     | 1.0    |
     33   # | activity period  | 0.5      | 0.5    |
     34   # | hunting range    | 1.0      | 2.0    |
     35   # | fur thickness    | -1.0     | 1.0    |
     36   # | tail length      | 0.0      | 0.0    |
     37 
     38   @impl true
     39   def fitness_function(chromosome) do
     40     tropic_scores = [0.0, 3.0, 2.0, -1.0, 0.5, 1.0, -1.0, 0.0]
     41     # tundra_scores = [1.0, 3.0, -2.0, 1.0, 0.5, 2.0, 1.0, 0.0]
     42     traits = chromosome.genes
     43 
     44     traits
     45     |> Enum.zip(tropic_scores)
     46     |> Enum.map(fn {t, s} -> t * s end)
     47     |> Enum.sum()
     48   end
     49 
     50   @impl true
     51   def terminate?(_population, generation), do: generation == 150
     52 
     53   def average_tiger(population) do
     54     genes = Enum.map(population, & &1.genes)
     55     fitness = Enum.map(population, & &1.fitness)
     56     ages = Enum.map(population, & &1.age)
     57     num_tigers = length(population)
     58 
     59     avg_fitness = Enum.sum(fitness) / num_tigers
     60     avg_age = Enum.sum(ages) / num_tigers
     61 
     62     avg_genes =
     63       genes
     64       |> Enum.zip()
     65       |> Enum.map(fn t -> Enum.sum(Tuple.to_list(t)) / num_tigers end)
     66 
     67     %Chromosome{genes: avg_genes, age: avg_age, fitness: avg_fitness, size: length(avg_genes)}
     68   end
     69 end
     70 
     71 {tiger, _generation} =
     72   Genetic.run(TigerSimulation,
     73     population_size: 100,
     74     selection_rate: 0.8,
     75     mutation_rate: 0.05,
     76     survival_rate: 0.2,
     77     mutation_type: &Toolbox.Mutation.flip/2,
     78     crossover_type: &Toolbox.Crossover.single_point/3
     79     # statistics: %{average_tiger: &TigerSimulation.average_tiger/1}
     80   )
     81 
     82 IO.puts("\nbest(?) tropical tiger: #{inspect(tiger.genes)}")
     83 # IO.puts("\nbest(?) tundra tiger: #{inspect(tiger.genes)}")
     84 
     85 genealogy = Utilities.Genealogy.get_tree()
     86 {:ok, dot} = Graph.Serializers.DOT.serialize(genealogy)
     87 {:ok, dotfile} = File.open("tiger_simulation.dot", [:write])
     88 :ok = IO.binwrite(dotfile, dot)
     89 :ok = File.close(dotfile)
     90 
     91 stats =
     92   :ets.tab2list(:statistics)
     93   |> Enum.sort_by(fn {gen, _stats} -> gen end)
     94   |> Enum.map(fn {gen, stats} -> [gen, stats.mean_fitness] end)
     95 
     96 {:ok, _} =
     97   Gnuplot.plot(
     98     [
     99       [:set, :title, "mean fitness versus generation (tiger_sim)"],
    100       [:plot, "-", :with, :points]
    101     ],
    102     [stats]
    103   )