From 321e4353d8d9a447c472bc5f0d3acbfcf0309bae Mon Sep 17 00:00:00 2001 From: Fredrik Robertsen Date: Fri, 6 Feb 2026 09:22:52 +0100 Subject: [PATCH] add elitism --- src/common.odin | 3 ++- src/ga.odin | 41 ++++++++++++++++++++++++++++++++++++++++- src/main.odin | 4 ++-- 3 files changed, 44 insertions(+), 4 deletions(-) diff --git a/src/common.odin b/src/common.odin index 3381a6d..c12f5c8 100644 --- a/src/common.odin +++ b/src/common.odin @@ -9,9 +9,10 @@ POPULATION_SIZE :: 100 GENERATIONS :: 100 TOURNAMENT_SIZE :: 3 CROSSOVER_RATE :: 0.8 -MUTATION_RATE :: 0.01 +MUTATION_RATE :: 0.05 RANDOM_SEED :: u64(42) OUTPUT_FILE :: "output/data.csv" +ELITISM_COUNT :: 2 Problem :: struct { name: string, diff --git a/src/ga.odin b/src/ga.odin index 8da4b18..7fc05a9 100644 --- a/src/ga.odin +++ b/src/ga.odin @@ -135,10 +135,25 @@ bit_flip_mutation :: proc(chrom: Chromosome) { } } +clone_chromosome :: proc(chrom: Chromosome) -> Chromosome { + size := bit_array.len(chrom) + clone := bit_array.create(size) + for i in 0 ..< size { + bit_array.set(clone, i, bit_array.get(chrom, i)) + } + return clone +} + create_offspring :: proc(pop: ^Population, fitnesses: []f64, maximize: bool) -> Population { offspring: Population - for i := 0; i < POPULATION_SIZE; i += 2 { + elite_idx := get_best_indices(fitnesses[:], ELITISM_COUNT, maximize) + defer delete(elite_idx) + for i in 0 ..< ELITISM_COUNT { + offspring[i] = clone_chromosome(pop[elite_idx[i]]) + } + + for i := ELITISM_COUNT; i < POPULATION_SIZE; i += 2 { parent1 := tournament_selection(pop, fitnesses, maximize) parent2 := tournament_selection(pop, fitnesses, maximize) @@ -158,6 +173,30 @@ create_offspring :: proc(pop: ^Population, fitnesses: []f64, maximize: bool) -> return offspring } +get_best_indices :: proc(fitnesses: []f64, count: int, maximize: bool) -> []int { + indices := make([]int, len(fitnesses)) + for i in 0 ..< len(indices) { + indices[i] = i + } + + // Partial sort for top N + for i in 0 ..< count { + best := i + for j in i + 1 ..< len(indices) { + is_better := maximize ? fitnesses[indices[j]] > fitnesses[indices[best]] : fitnesses[indices[j]] < fitnesses[indices[best]] + if is_better { + best = j + } + } + indices[i], indices[best] = indices[best], indices[i] + } + + result := make([]int, count) + copy(result, indices[:count]) + delete(indices) + return result +} + write_results :: proc(filename: string, stats: []Stats) -> bool { handle, err := os.open(filename, os.O_CREATE | os.O_WRONLY | os.O_TRUNC, 0o644) if err != os.ERROR_NONE {return false} diff --git a/src/main.odin b/src/main.odin index 017ea5d..5dc7010 100644 --- a/src/main.odin +++ b/src/main.odin @@ -8,8 +8,8 @@ main :: proc() { // Choose problem problem_type := "feature_selection" // or "knapsack" - state := rand.create(RANDOM_SEED) - context.random_generator = runtime.default_random_generator(&state) + // state := rand.create(RANDOM_SEED) + // context.random_generator = runtime.default_random_generator(&state) problem: Problem switch problem_type {