The function tournament_no_duplicates keeps hanging, because it will never reach n winners.
In a selection of n chromosomes you can never have n winners.
Maybe you will ever reach n-(tournsize-1) winners.
So I propose a different function.
def tournament_no_duplicates(problem, population, n, tournsize) do
set =
tournament(problem, population, n, tournsize)
|> MapSet.new()
|> MapSet.to_list()
# you get an error in crossover if this selection is not even.
# therefore I delete the weakest of the list
if rem(length(set), 2) == 0 do
set
else
Enum.sort_by(set, &problem.fitness_function(&1), :desc)
List.delete_at(set, -1)
end
end
Your selection could go to [ ],
therefore the population must be much bigger then the number of generations you run.
Yet you can reach good results.
I added this to the first part of evolve() in Genetic:
if population == [] do
IO.write("\n\nYou should make your population bigger\n\n")
raise "Watch it! Population is empty"
end
best = hd(population)
IO.inspect(best, label: "\n\nCurrent best:")
IO.write("Generation: #{generation}")