Initial commit
This commit is contained in:
77
lib/genetic.ex
Normal file
77
lib/genetic.ex
Normal file
@@ -0,0 +1,77 @@
|
||||
defmodule Genetic do
|
||||
alias Types.Chromosome
|
||||
|
||||
def initialize(genotype, opts \\ []) do
|
||||
population_size = Keyword.get(opts, :population_size, 100)
|
||||
for _ <- 1..population_size, do: genotype.()
|
||||
end
|
||||
|
||||
def evaluate(population, fitness_function, opts \\ []) do
|
||||
population
|
||||
|> Enum.map(
|
||||
fn chromosome ->
|
||||
fitness = fitness_function.(chromosome)
|
||||
age = chromosome.age + 1
|
||||
%Chromosome{chromosome | fitness: fitness, age: age}
|
||||
end
|
||||
)
|
||||
|> Enum.sort_by(& &1.fitness, &>=/2)
|
||||
end
|
||||
|
||||
def select(population, opts \\ []) do
|
||||
population
|
||||
|> Enum.chunk_every(2)
|
||||
|> Enum.map(&List.to_tuple(&1))
|
||||
end
|
||||
|
||||
def crossover(population, opts \\ []) do
|
||||
population
|
||||
|> Enum.reduce([],
|
||||
fn {p1, p2}, acc ->
|
||||
cx_point = :rand.uniform(length(p1.genes))
|
||||
{{h1,t1},{h2,t2}} =
|
||||
{Enum.split(p1.genes, cx_point),
|
||||
Enum.split(p2.genes, cx_point)}
|
||||
{c1,c2} = {%Chromosome{p1 | genes: h1 ++ t2}, %Chromosome{p2 | genes: h2 ++ t1} }
|
||||
[c1,c2 | acc]
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
def mutation(population, opts \\ []) do
|
||||
population
|
||||
|> Enum.map(
|
||||
fn chromosome ->
|
||||
if :rand.uniform() < 0.05 do
|
||||
%Chromosome{chromosome | genes: Enum.shuffle(chromosome)}
|
||||
else
|
||||
chromosome
|
||||
end
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
def run(problem, opts \\ []) do
|
||||
population = initialize(&problem.genotype/0)
|
||||
population
|
||||
|> evolve(problem, opts)
|
||||
end
|
||||
|
||||
def evolve(population, problem, opts \\ []) do
|
||||
population = evaluate(population, &problem.fitness_function/1, opts)
|
||||
best = hd(population)
|
||||
IO.write("\rCurrent Best: #{best.fitness}")
|
||||
if problem.terminate?(population) do
|
||||
best
|
||||
else
|
||||
population
|
||||
|> select(opts)
|
||||
|> crossover(opts)
|
||||
|> mutation(opts)
|
||||
|> evolve(problem, opts)
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
end
|
12
lib/types/chromosome.ex
Normal file
12
lib/types/chromosome.ex
Normal file
@@ -0,0 +1,12 @@
|
||||
defmodule Types.Chromosome do
|
||||
@type t :: %__MODULE__ {
|
||||
genes: Enum.t,
|
||||
size: integer(),
|
||||
fitness: number(),
|
||||
age: integer()
|
||||
}
|
||||
|
||||
|
||||
@enforce_keys :genes
|
||||
defstruct [:genes, size: 0, fitness: 0, age: 0]
|
||||
end
|
Reference in New Issue
Block a user