implement roulette selection for lower selection pressure

This commit is contained in:
2026-02-08 13:00:08 +01:00
parent 4ec008f689
commit 85d1aeb790
3 changed files with 51 additions and 8 deletions

View File

@@ -5,14 +5,17 @@ import "core:container/bit_array"
Chromosome :: ^bit_array.Bit_Array
Population :: [POPULATION_SIZE]Chromosome
POPULATION_SIZE :: 100
POPULATION_SIZE :: 1000
GENERATIONS :: 100
TOURNAMENT_SIZE :: 5
CROSSOVER_RATE :: 0.8
MUTATION_RATE :: 0.05
POPULATION_SIZE :: 1000
ELITISM_COUNT :: 10
SKEW :: 0
TOURNAMENT_SIZE :: 100
CROSSOVER_RATE :: 0.7
MUTATION_RATE :: 0.015
RANDOM_SEED :: u64(42)
OUTPUT_FILE :: "output/data.csv"
ELITISM_COUNT :: 2
ELITISM_COUNT :: 50
Problem :: struct {
name: string,

View File

@@ -102,6 +102,46 @@ tournament_selection :: proc(pop: ^Population, fitnesses: []f64, maximize: bool)
return pop[best_idx]
}
roulette_selection :: proc(pop: ^Population, fitnesses: []f64, maximize: bool) -> Chromosome {
adjusted_fitnesses := make([]f64, len(fitnesses), context.temp_allocator)
defer delete(adjusted_fitnesses, context.temp_allocator)
min_fitness := fitnesses[0]
if !maximize {
for f in fitnesses {
min_fitness = min(min_fitness, f)
}
}
total_fitness: f64 = 0
for i in 0..<len(fitnesses) {
if maximize {
adjusted_fitnesses[i] = max(fitnesses[i], 0)
} else {
// for minimization: invert so smaller values get higher probability
adjusted_fitnesses[i] = max(min_fitness - fitnesses[i] + 1e-6, 0)
}
total_fitness += adjusted_fitnesses[i]
}
if total_fitness <= 0 {
return pop[rand.int_max(POPULATION_SIZE)]
}
spin := rand.float64() * total_fitness
cumulative: f64 = 0
for i in 0..<len(adjusted_fitnesses) {
cumulative += adjusted_fitnesses[i]
if cumulative >= spin {
return pop[i]
}
}
return pop[len(pop) - 1]
}
two_point_crossover :: proc(parent1, parent2: Chromosome) -> (Chromosome, Chromosome) {
size := bit_array.len(parent1)
point1 := rand.int_max(size)
@@ -172,8 +212,8 @@ create_offspring :: proc(pop: ^Population, fitnesses: []f64, maximize: bool) ->
}
for i := ELITISM_COUNT; i < POPULATION_SIZE; i += 2 {
parent1 := tournament_selection(pop, fitnesses, maximize)
parent2 := tournament_selection(pop, fitnesses, maximize)
parent1 := roulette_selection(pop, fitnesses, maximize)
parent2 := roulette_selection(pop, fitnesses, maximize)
child1, child2 := uniform_crossover(parent1, parent2)

View File

@@ -6,7 +6,7 @@ import "base:runtime"
main :: proc() {
// Choose problem
problem_type := "feature_selection" // or "knapsack"
problem_type := "knapsack" // or "knapsack"
// state := rand.create(RANDOM_SEED)
// context.random_generator = runtime.default_random_generator(&state)