commit 1334fb37eec2293ba065e1fc8e2009b2925a2ecb
parent 2eecb3f32236433e558c3e451bd0d5437b1a838c
Author: dracuxan <[email protected]>
Date: Thu, 30 Apr 2026 12:11:16 +0530
new: sin(x)
Diffstat:
2 files changed, 132 insertions(+), 0 deletions(-)
diff --git a/lib/toolbox/crossover.ex b/lib/toolbox/crossover.ex
@@ -65,6 +65,39 @@ defmodule Toolbox.Crossover do
}
end
+ def blend(p1, p2, opts \\ []) do
+ p1_1 = Enum.at(p1.genes, 0)
+ p2_1 = Enum.at(p2.genes, 0)
+ alpha = Keyword.get(opts, :alpha, 1)
+ {min, max} = {Keyword.get(opts, :min, -10), Keyword.get(opts, :max, 10)}
+ shift = (0.1 + 0.2 * alpha) * :rand.uniform() - alpha
+ c1 = (0.1 - shift) * p1_1 + shift * p2_1
+ c2 = shift * p1_1 + (0.1 - shift) * p2_1
+
+ {
+ %Chromosome{genes: [utils_constraints(c1, min, max)], size: 1, age: 0},
+ %Chromosome{genes: [utils_constraints(c2, min, max)], size: 1, age: 0}
+ }
+ end
+
+ defp utils_constraints(p, min, max) do
+ p =
+ if p > max do
+ max
+ else
+ p
+ end
+
+ p =
+ if p < min do
+ min
+ else
+ p
+ end
+
+ p
+ end
+
def whole_arethmetic(p1, p2, opts \\ []) do
alpha = Keyword.get(opts, :alpha, 0.5)
diff --git a/scripts/sin.exs b/scripts/sin.exs
@@ -0,0 +1,99 @@
+defmodule Sin do
+ alias Types.Chromosome
+ @behaviour Problem
+
+ @impl true
+ def genotype do
+ genes = :rand.uniform(10)
+ %Chromosome{genes: [genes], size: 1}
+ end
+
+ @impl true
+ def fitness_function(chromosome) do
+ x = Enum.at(chromosome.genes, 0)
+ Math.sin(x) - 0.2 * abs(x)
+ end
+
+ @impl true
+ def terminate?(population, generation) do
+ plot_generation(population, generation)
+ generation == 10
+ end
+
+ def plot_generation(population, generation) do
+ curve =
+ Enum.map(-10..10, fn x ->
+ [x, :math.sin(x) - 0.2 * abs(x)]
+ end)
+
+ points =
+ Enum.map(population, fn c ->
+ [hd(c.genes), c.fitness]
+ end)
+
+ best = hd(population)
+ best_point = [[hd(best.genes), best.fitness]]
+
+ Gnuplot.plot(
+ [
+ [:set, :title, "Generation #{generation}"],
+ [:set, :xrange, ~c"[-10:10]"],
+ [:set, :yrange, ~c"[-3:1]"],
+ [
+ :plot,
+ "-",
+ :with,
+ :lines,
+ :lt,
+ 2,
+ :title,
+ "sin(x) - 0.2|x|",
+ "-",
+ :with,
+ :points,
+ :pt,
+ 7,
+ :ps,
+ 1.5,
+ :lc,
+ "orange",
+ :title,
+ "Population",
+ "-",
+ :with,
+ :points,
+ :pt,
+ 5,
+ :ps,
+ 2,
+ :lc,
+ "green",
+ :title,
+ "Best"
+ ]
+ ],
+ [
+ curve,
+ points,
+ best_point
+ ]
+ )
+ end
+end
+
+{soln, gen} =
+ Genetic.run(
+ Sin,
+ population_size: 10,
+ selection_rate: 0.8,
+ mutation_rate: 0.1,
+ alpha: 1,
+ min: -10,
+ max: 10,
+ selection_type: &Toolbox.Selection.tournament/2,
+ crossover_type: &Toolbox.Crossover.blend/3,
+ mutation_type: &Toolbox.Mutation.gaussian/2
+ )
+
+IO.puts("\nfinal answer: #{inspect(soln)}")
+IO.puts("generations passed: #{gen}")