genetic

genetic algorithm framework
git clone igris.git:dracuxan/genetic.git
Log | Files | Refs | README

commit 1334fb37eec2293ba065e1fc8e2009b2925a2ecb
parent 2eecb3f32236433e558c3e451bd0d5437b1a838c
Author: dracuxan <[email protected]>
Date:   Thu, 30 Apr 2026 12:11:16 +0530

new: sin(x)

Diffstat:
Mlib/toolbox/crossover.ex | 33+++++++++++++++++++++++++++++++++
Ascripts/sin.exs | 99+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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}")