Skip to content

Commit 7ca565f

Browse files
committed
add temperature termination condition
1 parent 1e51607 commit 7ca565f

File tree

5 files changed

+33
-28
lines changed

5 files changed

+33
-28
lines changed

lib/genetic.ex

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ defmodule Genetic do
66
for _ <- 1..population_size, do: genotype.()
77
end
88

9-
def evaluate(population, fitness_function, _opts \\ []) do
9+
def evaluate(population, generation, fitness_function, _opts \\ []) do
1010
population
1111
|> Enum.map(
1212
fn chromosome ->
1313
fitness = fitness_function.(chromosome)
14-
age = chromosome.age + 1
14+
age = if generation == 0, do: chromosome.age, else: chromosome.age + 1
1515
%Chromosome{chromosome | fitness: fitness, age: age}
1616
end
1717
)
@@ -20,8 +20,8 @@ defmodule Genetic do
2020

2121
def select(population, _opts \\ []) do
2222
population
23-
|> Enum.chunk_every(2)
24-
|> Enum.map(&List.to_tuple(&1))
23+
|> Enum.chunk_every(2)
24+
|> Enum.map(&List.to_tuple(&1))
2525
end
2626

2727
def crossover(population, _opts \\ []) do
@@ -54,27 +54,26 @@ defmodule Genetic do
5454
end
5555

5656
def run(problem, opts \\ []) do
57-
population = initialize(&problem.genotype/0)
58-
first_generation = 0
57+
population = initialize(&problem.genotype/0, opts)
5958

6059
population
61-
|> evolve(problem, first_generation, opts)
60+
|> evolve(problem, 0, 0, 100, opts)
6261
end
6362

64-
def evolve(population, problem, generation, opts \\ []) do
65-
population = evaluate(population, &problem.fitness_function/1, opts)
63+
def evolve(population, problem, generation, last_max_fitness, temperature, opts \\ []) do
64+
population = evaluate(population, generation, &problem.fitness_function/1, opts)
6665
best = hd(population)
67-
IO.write("\rCurrent Best: #{problem.fitness_function(best)}")
68-
if problem.terminate?(population, generation) do
66+
best_fitness = best.fitness
67+
temperature = 0.9 * (temperature + (best_fitness - last_max_fitness))
68+
IO.write("\rCurrent Best: #{problem.fitness_function(best)}, temp: #{temperature}")
69+
if problem.terminate?(population, generation, temperature) do
6970
best
7071
else
71-
generation = generation + 1
72-
7372
population
74-
|> select(opts)
75-
|> crossover(opts)
76-
|> mutation(opts)
77-
|> evolve(problem, generation, opts)
73+
|> select(opts)
74+
|> crossover(opts)
75+
|> mutation(opts)
76+
|> evolve(problem, generation + 1, best_fitness, temperature, opts)
7877
end
7978
end
8079
end

lib/problem.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@ defmodule Problem do
33

44
@callback genotype :: Chromosome.t
55
@callback fitness_function(Chromosome.t) :: number()
6-
@callback terminate?(Enum.t(), integer()) :: boolean()
6+
@callback terminate?(Enum.t(), integer(), number()) :: boolean()
77
end

scripts/cargo.exs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ defmodule Cargo do
3232
end
3333

3434
@impl true
35-
def terminate?(_population, generation), do: generation == 100
35+
def terminate?(_population, generation, _temperature) do
36+
generation == 100
37+
end
3638
end
3739

3840
solution = Genetic.run(Cargo, population_size: 50)

scripts/one_max.exs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,19 @@ defmodule OneMax do
44

55
@impl true
66
def genotype do
7-
genes = for _ <- 1..42, do: Enum.random(0..1)
8-
%Chromosome{genes: genes, size: 42}
7+
genes = for _ <- 1..100, do: Enum.random(0..1)
8+
%Chromosome{genes: genes, size: 100}
99
end
1010

1111
@impl true
1212
def fitness_function(chromosome), do: Enum.sum(chromosome.genes)
1313

1414
@impl true
15-
def terminate?(_population, generation), do: generation == 100
15+
def terminate?(_population, _generation, temperature) do
16+
temperature < 1
17+
end
1618
end
1719

18-
solution = Genetic.run(OneMax)
20+
solution = Genetic.run(OneMax, population_size: 1000)
1921
IO.write("\n")
2022
IO.inspect(solution)

scripts/speller.exs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,25 @@ defmodule Speller do
55
@impl true
66
def genotype do
77
genes = Stream.repeatedly(fn -> Enum.random(?a..?z) end)
8-
|> Enum.take(6)
8+
|> Enum.take(34)
99

10-
%Chromosome{genes: genes, size: 6}
10+
%Chromosome{genes: genes, size: 34}
1111
end
1212

1313
@impl true
1414
def fitness_function(chromosome) do
15-
target = "sekrit"
15+
target = "supercalifragilisticexpialidocious"
1616
guess = List.to_string(chromosome.genes)
1717
String.jaro_distance(target, guess)
1818
end
1919

2020
@impl true
21-
def terminate?(_population, generation), do: generation == 100
21+
def terminate?(_population, _generation, temperature) do
22+
temperature < 0.01
23+
end
2224
end
2325

24-
solution = Genetic.run(Speller)
26+
solution = Genetic.run(Speller, population_size: 1000)
2527
IO.write("\n")
2628
IO.inspect(solution)
2729

0 commit comments

Comments
 (0)