genetic

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

n_queens.exs (1771B)


      1 defmodule NQueens do
      2   alias Types.Chromosome
      3   @behaviour Problem
      4 
      5   @max_queens 12
      6   @target_fitness @max_queens + 1
      7   @size @target_fitness
      8 
      9   @impl true
     10   def genotype do
     11     genes = Enum.shuffle(0..@max_queens)
     12     %Chromosome{genes: genes, size: @size}
     13   end
     14 
     15   @impl true
     16   def fitness_function(chromosome) do
     17     diag_clashes =
     18       for i <- 0..@max_queens, j <- 0..@max_queens do
     19         if i != j do
     20           dx = abs(i - j)
     21           dy = abs(Enum.at(chromosome.genes, i) - Enum.at(chromosome.genes, j))
     22           if dx == dy, do: 1, else: 0
     23         else
     24           0
     25         end
     26       end
     27 
     28     length(Enum.uniq(chromosome.genes)) - Enum.sum(diag_clashes)
     29   end
     30 
     31   @impl true
     32   def terminate?(population, _generation) do
     33     best = hd(population)
     34     best.fitness == @target_fitness
     35   end
     36 
     37   def map_queens(soln) do
     38     size = length(soln)
     39 
     40     for i <- 0..(size - 1) do
     41       row_string =
     42         for j <- 0..(size - 1) do
     43           if(Enum.at(soln, i) == j) do
     44             " Q "
     45           else
     46             " . "
     47           end
     48         end
     49         |> Enum.join()
     50 
     51       IO.puts(row_string)
     52     end
     53   end
     54 end
     55 
     56 {soln, generation} =
     57   Genetic.run(
     58     NQueens,
     59     selection_type: &Toolbox.Selection.elite/2,
     60     mutation_type: &Toolbox.Mutation.scramble/2,
     61     crossover_type: &Toolbox.Crossover.order_one/3
     62   )
     63 
     64 IO.puts("\nfinal answer: #{inspect(soln.genes)}\ngenrations passed: #{generation}")
     65 NQueens.map_queens(soln.genes)
     66 
     67 # stats =
     68 #   :ets.tab2list(:statistics)
     69 #   |> Enum.sort_by(fn {gen, _stat} -> gen end)
     70 #   |> Enum.map(fn {gen, stats} -> [gen, stats.mean_fitness] end)
     71 #
     72 # {:ok, _} =
     73 #   Gnuplot.plot(
     74 #     [
     75 #       [:set, :title, "mean fitness versus generation (n__queens)"],
     76 #       [:plot, "-", :with, :points]
     77 #     ],
     78 #     [stats]
     79 #   )