commit ba76f5047ee8ec89459d35ff65622e1188a305b0
parent 734900580f9b151a2050eb45433d09ffe10c8ffb
Author: dracuxan <[email protected]>
Date: Wed, 8 Apr 2026 14:03:56 +0530
new: whole arithmetic crossover and demo of multi parent crossover
Diffstat:
1 file changed, 51 insertions(+), 14 deletions(-)
diff --git a/genetic/lib/toolbox/crossover.ex b/genetic/lib/toolbox/crossover.ex
@@ -24,16 +24,10 @@ defmodule Toolbox.Crossover do
# create and return
{c1, c2} = {head1 ++ slice1 ++ tail1, head2 ++ slice2 ++ tail2}
- {%Chromosome{
- genes: c1,
- size: p1.size,
- age: 0
- },
- %Chromosome{
- genes: c2,
- size: p2.size,
- age: 0
- }}
+ {
+ %Chromosome{genes: c1, size: length(c1), age: 0},
+ %Chromosome{genes: c2, size: length(c2), age: 0}
+ }
end
def single_point(p1, p2, _opts \\ []) do
@@ -45,8 +39,8 @@ defmodule Toolbox.Crossover do
{c1, c2} = {head1 ++ tail2, head2 ++ tail1}
{
- %Chromosome{genes: c1, size: p1.size, age: 0},
- %Chromosome{genes: c2, size: p2.size, age: 0}
+ %Chromosome{genes: c1, size: length(c1), age: 0},
+ %Chromosome{genes: c2, size: length(c2), age: 0}
}
end
@@ -66,8 +60,51 @@ defmodule Toolbox.Crossover do
|> Enum.unzip()
{
- %Chromosome{genes: c1, size: p1.size, age: 0},
- %Chromosome{genes: c2, size: p2.size, age: 0}
+ %Chromosome{genes: c1, size: length(c1), age: 0},
+ %Chromosome{genes: c2, size: length(c2), age: 0}
+ }
+ end
+
+ def whole_arethmetic(p1, p2, opts \\ []) do
+ alpha = Keyword.get(opts, :alpha, 0.5)
+
+ {c1, c2} =
+ p1.genes
+ |> Enum.zip(p2.genes)
+ |> Enum.map(fn {x, y} ->
+ {
+ x * alpha + y * (1 - alpha),
+ x * (alpha - 1) + y * alpha
+ }
+ end)
+ |> Enum.unzip()
+
+ {
+ %Chromosome{genes: c1, size: length(c1), age: 0},
+ %Chromosome{genes: c2, size: length(c2), age: 0}
}
end
+
+ # demo of how crossover can be performed on mulitple parents at once
+ def single_point_multi(parents, opts \\ [])
+ def single_point_multi([], _opts), do: raise("more than one parent needed!")
+ def single_point_multi([p1 | []], _opts), do: p1
+
+ def single_point_multi(parents, _opts) do
+ p1 = hd(parents)
+ cx_point = :rand.uniform(p1.size)
+
+ parents
+ |> Enum.chunk_every(2, 1, [hd(parents)])
+ |> Enum.map(&List.to_tuple(&1))
+ |> Enum.reduce(
+ [],
+ fn {p1, p2}, chd ->
+ {front, _} = Enum.split(p1.genes, cx_point)
+ {_, back} = Enum.split(p2.genes, cx_point)
+ c = %Chromosome{genes: front ++ back, size: length(p1)}
+ [c | chd]
+ end
+ )
+ end
end