From a7c70462b23d9c4381d2f729244abc19d73f74c2 Mon Sep 17 00:00:00 2001 From: Fredrik Robertsen Date: Sun, 8 Feb 2026 22:45:40 +0100 Subject: [PATCH] readd single-point and some mutation operators --- src/common.odin | 6 ++--- src/ga.odin | 62 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 3 deletions(-) diff --git a/src/common.odin b/src/common.odin index b9e74f8..92f9e2a 100644 --- a/src/common.odin +++ b/src/common.odin @@ -13,10 +13,10 @@ TOURNAMENT_SIZE :: 5 CROSSOVER_RATE :: 0.7 MUTATION_RATE :: 0.01 -SURVIVOR_SELECTION_POLICY :: probabilistic_crowding -PARENT_SELECTION_POLICY :: roulette_selection -CROSSOVER_POLICY :: uniform_crossover +PARENT_SELECTION_POLICY :: random_selection +CROSSOVER_POLICY :: single_point_crossover MUTATION_POLICY :: bit_flip_mutation +SURVIVOR_SELECTION_POLICY :: generational_replacement RANDOM_SEED :: u64(42) OUTPUT_FILE :: "output/data.csv" diff --git a/src/ga.odin b/src/ga.odin index 84d2253..e0966bc 100644 --- a/src/ga.odin +++ b/src/ga.odin @@ -206,6 +206,29 @@ roulette_selection :: proc(pop: ^Population, fitnesses: []f64, maximize: bool) - return pop[len(pop) - 1] } +single_point_crossover :: proc(parent1, parent2: Chromosome) -> (Chromosome, Chromosome) { + if rand.float64() > CROSSOVER_RATE { + return clone_chromosome(parent1), clone_chromosome(parent2) + } + + size := bit_array.len(parent1) + point := rand.int_max(size) + + child1 := bit_array.create(size) + child2 := bit_array.create(size) + + for i in 0 ..< point { + bit_array.set(child1, i, bit_array.get(parent1, i)) + bit_array.set(child2, i, bit_array.get(parent2, i)) + } + + for i in point ..< size { + bit_array.set(child1, i, bit_array.get(parent2, i)) + bit_array.set(child2, i, bit_array.get(parent1, i)) + } + + return child1, child2 +} two_point_crossover :: proc(parent1, parent2: Chromosome) -> (Chromosome, Chromosome) { size := bit_array.len(parent1) @@ -258,6 +281,45 @@ bit_flip_mutation :: proc(chrom: Chromosome) { } } +swap_mutation :: proc(chromosome: Chromosome) { + size := bit_array.len(chromosome) + if rand.float64() < MUTATION_RATE { + i := rand.int_max(size) + j := rand.int_max(size) + + bit_i := bit_array.get(chromosome, i) + bit_j := bit_array.get(chromosome, j) + + bit_array.set(chromosome, i, bit_j) + bit_array.set(chromosome, j, bit_i) + } +} + +inversion_mutation :: proc(chromosome: Chromosome) { + size := bit_array.len(chromosome) + if rand.float64() < MUTATION_RATE { + point1 := rand.int_max(size) + point2 := rand.int_max(size) + + if point1 > point2 { + point1, point2 = point2, point1 + } + + // Reverse segment + for i := 0; i < (point2 - point1 + 1) / 2; i += 1 { + left := point1 + i + right := point2 - i + + bit_left := bit_array.get(chromosome, left) + bit_right := bit_array.get(chromosome, right) + + bit_array.set(chromosome, left, bit_right) + bit_array.set(chromosome, right, bit_left) + } + } +} + + clone_chromosome :: proc(chrom: Chromosome) -> Chromosome { size := bit_array.len(chrom) clone := bit_array.create(size)