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 # )